2 * shmob_drm_kms.c -- SH Mobile DRM Mode Setting
4 * Copyright (C) 2012 Renesas Electronics Corporation
6 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
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.
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 #include <drm/drm_gem_framebuffer_helper.h>
21 #include "shmob_drm_crtc.h"
22 #include "shmob_drm_drv.h"
23 #include "shmob_drm_kms.h"
24 #include "shmob_drm_regs.h"
26 /* -----------------------------------------------------------------------------
30 static const struct shmob_drm_format_info shmob_drm_format_infos
[] = {
32 .fourcc
= DRM_FORMAT_RGB565
,
35 .lddfr
= LDDFR_PKF_RGB16
,
37 .fourcc
= DRM_FORMAT_RGB888
,
40 .lddfr
= LDDFR_PKF_RGB24
,
42 .fourcc
= DRM_FORMAT_ARGB8888
,
45 .lddfr
= LDDFR_PKF_ARGB32
,
47 .fourcc
= DRM_FORMAT_NV12
,
50 .lddfr
= LDDFR_CC
| LDDFR_YF_420
,
52 .fourcc
= DRM_FORMAT_NV21
,
55 .lddfr
= LDDFR_CC
| LDDFR_YF_420
,
57 .fourcc
= DRM_FORMAT_NV16
,
60 .lddfr
= LDDFR_CC
| LDDFR_YF_422
,
62 .fourcc
= DRM_FORMAT_NV61
,
65 .lddfr
= LDDFR_CC
| LDDFR_YF_422
,
67 .fourcc
= DRM_FORMAT_NV24
,
70 .lddfr
= LDDFR_CC
| LDDFR_YF_444
,
72 .fourcc
= DRM_FORMAT_NV42
,
75 .lddfr
= LDDFR_CC
| LDDFR_YF_444
,
79 const struct shmob_drm_format_info
*shmob_drm_format_info(u32 fourcc
)
83 for (i
= 0; i
< ARRAY_SIZE(shmob_drm_format_infos
); ++i
) {
84 if (shmob_drm_format_infos
[i
].fourcc
== fourcc
)
85 return &shmob_drm_format_infos
[i
];
91 /* -----------------------------------------------------------------------------
95 static struct drm_framebuffer
*
96 shmob_drm_fb_create(struct drm_device
*dev
, struct drm_file
*file_priv
,
97 const struct drm_mode_fb_cmd2
*mode_cmd
)
99 const struct shmob_drm_format_info
*format
;
101 format
= shmob_drm_format_info(mode_cmd
->pixel_format
);
102 if (format
== NULL
) {
103 dev_dbg(dev
->dev
, "unsupported pixel format %08x\n",
104 mode_cmd
->pixel_format
);
105 return ERR_PTR(-EINVAL
);
108 if (mode_cmd
->pitches
[0] & 7 || mode_cmd
->pitches
[0] >= 65536) {
109 dev_dbg(dev
->dev
, "invalid pitch value %u\n",
110 mode_cmd
->pitches
[0]);
111 return ERR_PTR(-EINVAL
);
115 unsigned int chroma_cpp
= format
->bpp
== 24 ? 2 : 1;
117 if (mode_cmd
->pitches
[1] != mode_cmd
->pitches
[0] * chroma_cpp
) {
119 "luma and chroma pitches do not match\n");
120 return ERR_PTR(-EINVAL
);
124 return drm_gem_fb_create(dev
, file_priv
, mode_cmd
);
127 static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs
= {
128 .fb_create
= shmob_drm_fb_create
,
131 int shmob_drm_modeset_init(struct shmob_drm_device
*sdev
)
133 drm_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
);