1 // SPDX-License-Identifier: GPL-2.0+
3 * shmob_drm_kms.c -- SH Mobile DRM Mode Setting
5 * Copyright (C) 2012 Renesas Electronics Corporation
7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
10 #include <drm/drm_crtc.h>
11 #include <drm/drm_crtc_helper.h>
12 #include <drm/drm_fb_cma_helper.h>
13 #include <drm/drm_gem_cma_helper.h>
14 #include <drm/drm_gem_framebuffer_helper.h>
15 #include <drm/drm_probe_helper.h>
17 #include "shmob_drm_crtc.h"
18 #include "shmob_drm_drv.h"
19 #include "shmob_drm_kms.h"
20 #include "shmob_drm_regs.h"
22 /* -----------------------------------------------------------------------------
26 static const struct shmob_drm_format_info shmob_drm_format_infos
[] = {
28 .fourcc
= DRM_FORMAT_RGB565
,
31 .lddfr
= LDDFR_PKF_RGB16
,
33 .fourcc
= DRM_FORMAT_RGB888
,
36 .lddfr
= LDDFR_PKF_RGB24
,
38 .fourcc
= DRM_FORMAT_ARGB8888
,
41 .lddfr
= LDDFR_PKF_ARGB32
,
43 .fourcc
= DRM_FORMAT_NV12
,
46 .lddfr
= LDDFR_CC
| LDDFR_YF_420
,
48 .fourcc
= DRM_FORMAT_NV21
,
51 .lddfr
= LDDFR_CC
| LDDFR_YF_420
,
53 .fourcc
= DRM_FORMAT_NV16
,
56 .lddfr
= LDDFR_CC
| LDDFR_YF_422
,
58 .fourcc
= DRM_FORMAT_NV61
,
61 .lddfr
= LDDFR_CC
| LDDFR_YF_422
,
63 .fourcc
= DRM_FORMAT_NV24
,
66 .lddfr
= LDDFR_CC
| LDDFR_YF_444
,
68 .fourcc
= DRM_FORMAT_NV42
,
71 .lddfr
= LDDFR_CC
| LDDFR_YF_444
,
75 const struct shmob_drm_format_info
*shmob_drm_format_info(u32 fourcc
)
79 for (i
= 0; i
< ARRAY_SIZE(shmob_drm_format_infos
); ++i
) {
80 if (shmob_drm_format_infos
[i
].fourcc
== fourcc
)
81 return &shmob_drm_format_infos
[i
];
87 /* -----------------------------------------------------------------------------
91 static struct drm_framebuffer
*
92 shmob_drm_fb_create(struct drm_device
*dev
, struct drm_file
*file_priv
,
93 const struct drm_mode_fb_cmd2
*mode_cmd
)
95 const struct shmob_drm_format_info
*format
;
97 format
= shmob_drm_format_info(mode_cmd
->pixel_format
);
99 dev_dbg(dev
->dev
, "unsupported pixel format %08x\n",
100 mode_cmd
->pixel_format
);
101 return ERR_PTR(-EINVAL
);
104 if (mode_cmd
->pitches
[0] & 7 || mode_cmd
->pitches
[0] >= 65536) {
105 dev_dbg(dev
->dev
, "invalid pitch value %u\n",
106 mode_cmd
->pitches
[0]);
107 return ERR_PTR(-EINVAL
);
111 unsigned int chroma_cpp
= format
->bpp
== 24 ? 2 : 1;
113 if (mode_cmd
->pitches
[1] != mode_cmd
->pitches
[0] * chroma_cpp
) {
115 "luma and chroma pitches do not match\n");
116 return ERR_PTR(-EINVAL
);
120 return drm_gem_fb_create(dev
, file_priv
, mode_cmd
);
123 static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs
= {
124 .fb_create
= shmob_drm_fb_create
,
127 int shmob_drm_modeset_init(struct shmob_drm_device
*sdev
)
131 ret
= drmm_mode_config_init(sdev
->ddev
);
135 shmob_drm_crtc_create(sdev
);
136 shmob_drm_encoder_create(sdev
);
137 shmob_drm_connector_create(sdev
, &sdev
->encoder
.encoder
);
139 drm_kms_helper_poll_init(sdev
->ddev
);
141 sdev
->ddev
->mode_config
.min_width
= 0;
142 sdev
->ddev
->mode_config
.min_height
= 0;
143 sdev
->ddev
->mode_config
.max_width
= 4095;
144 sdev
->ddev
->mode_config
.max_height
= 4095;
145 sdev
->ddev
->mode_config
.funcs
= &shmob_drm_mode_config_funcs
;
147 drm_helper_disable_unused_functions(sdev
->ddev
);