Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
shmob_drm_kms.c
Go to the documentation of this file.
1 /*
2  * shmob_drm_kms.c -- SH Mobile DRM Mode Setting
3  *
4  * Copyright (C) 2012 Renesas Corporation
5  *
6  * Laurent Pinchart ([email protected])
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13 
14 #include <drm/drmP.h>
15 #include <drm/drm_crtc.h>
16 #include <drm/drm_crtc_helper.h>
17 #include <drm/drm_fb_cma_helper.h>
18 #include <drm/drm_gem_cma_helper.h>
19 
20 #include <video/sh_mobile_meram.h>
21 
22 #include "shmob_drm_crtc.h"
23 #include "shmob_drm_drv.h"
24 #include "shmob_drm_kms.h"
25 #include "shmob_drm_regs.h"
26 
27 /* -----------------------------------------------------------------------------
28  * Format helpers
29  */
30 
31 static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
32  {
33  .fourcc = DRM_FORMAT_RGB565,
34  .bpp = 16,
35  .yuv = false,
36  .lddfr = LDDFR_PKF_RGB16,
37  .meram = SH_MOBILE_MERAM_PF_RGB,
38  }, {
39  .fourcc = DRM_FORMAT_RGB888,
40  .bpp = 24,
41  .yuv = false,
42  .lddfr = LDDFR_PKF_RGB24,
43  .meram = SH_MOBILE_MERAM_PF_RGB,
44  }, {
45  .fourcc = DRM_FORMAT_ARGB8888,
46  .bpp = 32,
47  .yuv = false,
48  .lddfr = LDDFR_PKF_ARGB32,
49  .meram = SH_MOBILE_MERAM_PF_RGB,
50  }, {
51  .fourcc = DRM_FORMAT_NV12,
52  .bpp = 12,
53  .yuv = true,
54  .lddfr = LDDFR_CC | LDDFR_YF_420,
55  .meram = SH_MOBILE_MERAM_PF_NV,
56  }, {
57  .fourcc = DRM_FORMAT_NV21,
58  .bpp = 12,
59  .yuv = true,
60  .lddfr = LDDFR_CC | LDDFR_YF_420,
61  .meram = SH_MOBILE_MERAM_PF_NV,
62  }, {
63  .fourcc = DRM_FORMAT_NV16,
64  .bpp = 16,
65  .yuv = true,
66  .lddfr = LDDFR_CC | LDDFR_YF_422,
67  .meram = SH_MOBILE_MERAM_PF_NV,
68  }, {
69  .fourcc = DRM_FORMAT_NV61,
70  .bpp = 16,
71  .yuv = true,
72  .lddfr = LDDFR_CC | LDDFR_YF_422,
73  .meram = SH_MOBILE_MERAM_PF_NV,
74  }, {
75  .fourcc = DRM_FORMAT_NV24,
76  .bpp = 24,
77  .yuv = true,
78  .lddfr = LDDFR_CC | LDDFR_YF_444,
79  .meram = SH_MOBILE_MERAM_PF_NV24,
80  }, {
81  .fourcc = DRM_FORMAT_NV42,
82  .bpp = 24,
83  .yuv = true,
84  .lddfr = LDDFR_CC | LDDFR_YF_444,
85  .meram = SH_MOBILE_MERAM_PF_NV24,
86  },
87 };
88 
90 {
91  unsigned int i;
92 
93  for (i = 0; i < ARRAY_SIZE(shmob_drm_format_infos); ++i) {
94  if (shmob_drm_format_infos[i].fourcc == fourcc)
95  return &shmob_drm_format_infos[i];
96  }
97 
98  return NULL;
99 }
100 
101 /* -----------------------------------------------------------------------------
102  * Frame buffer
103  */
104 
105 static struct drm_framebuffer *
106 shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
107  struct drm_mode_fb_cmd2 *mode_cmd)
108 {
109  const struct shmob_drm_format_info *format;
110 
111  format = shmob_drm_format_info(mode_cmd->pixel_format);
112  if (format == NULL) {
113  dev_dbg(dev->dev, "unsupported pixel format %08x\n",
114  mode_cmd->pixel_format);
115  return ERR_PTR(-EINVAL);
116  }
117 
118  if (mode_cmd->pitches[0] & 7 || mode_cmd->pitches[0] >= 65536) {
119  dev_dbg(dev->dev, "valid pitch value %u\n",
120  mode_cmd->pitches[0]);
121  return ERR_PTR(-EINVAL);
122  }
123 
124  if (format->yuv) {
125  unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;
126 
127  if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {
128  dev_dbg(dev->dev,
129  "luma and chroma pitches do not match\n");
130  return ERR_PTR(-EINVAL);
131  }
132  }
133 
134  return drm_fb_cma_create(dev, file_priv, mode_cmd);
135 }
136 
137 static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {
138  .fb_create = shmob_drm_fb_create,
139 };
140 
142 {
143  drm_mode_config_init(sdev->ddev);
144 
145  shmob_drm_crtc_create(sdev);
147  shmob_drm_connector_create(sdev, &sdev->encoder.encoder);
148 
150 
151  sdev->ddev->mode_config.min_width = 0;
152  sdev->ddev->mode_config.min_height = 0;
153  sdev->ddev->mode_config.max_width = 4095;
154  sdev->ddev->mode_config.max_height = 4095;
155  sdev->ddev->mode_config.funcs = &shmob_drm_mode_config_funcs;
156 
158 
159  return 0;
160 }