xref: /linux/drivers/gpu/drm/renesas/shmobile/shmob_drm_kms.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
111696c5eSBiju Das // SPDX-License-Identifier: GPL-2.0+
211696c5eSBiju Das /*
311696c5eSBiju Das  * shmob_drm_kms.c  --  SH Mobile DRM Mode Setting
411696c5eSBiju Das  *
511696c5eSBiju Das  * Copyright (C) 2012 Renesas Electronics Corporation
611696c5eSBiju Das  *
711696c5eSBiju Das  * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
811696c5eSBiju Das  */
911696c5eSBiju Das 
10*4afa0410SGeert Uytterhoeven #include <drm/drm_atomic_helper.h>
1111696c5eSBiju Das #include <drm/drm_crtc.h>
1211696c5eSBiju Das #include <drm/drm_crtc_helper.h>
1311696c5eSBiju Das #include <drm/drm_fourcc.h>
1411696c5eSBiju Das #include <drm/drm_gem_dma_helper.h>
1511696c5eSBiju Das #include <drm/drm_gem_framebuffer_helper.h>
1611696c5eSBiju Das #include <drm/drm_probe_helper.h>
1711696c5eSBiju Das 
1811696c5eSBiju Das #include "shmob_drm_crtc.h"
1911696c5eSBiju Das #include "shmob_drm_drv.h"
2011696c5eSBiju Das #include "shmob_drm_kms.h"
21*4afa0410SGeert Uytterhoeven #include "shmob_drm_plane.h"
2211696c5eSBiju Das #include "shmob_drm_regs.h"
2311696c5eSBiju Das 
2411696c5eSBiju Das /* -----------------------------------------------------------------------------
2511696c5eSBiju Das  * Format helpers
2611696c5eSBiju Das  */
2711696c5eSBiju Das 
2811696c5eSBiju Das static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
2911696c5eSBiju Das 	{
3011696c5eSBiju Das 		.fourcc = DRM_FORMAT_RGB565,
3111696c5eSBiju Das 		.bpp = 16,
3211696c5eSBiju Das 		.lddfr = LDDFR_PKF_RGB16,
337802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS | LDDDSR_WS,
347802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
357802ca6bSGeert Uytterhoeven 			    LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16,
3611696c5eSBiju Das 	}, {
3711696c5eSBiju Das 		.fourcc = DRM_FORMAT_RGB888,
3811696c5eSBiju Das 		.bpp = 24,
3911696c5eSBiju Das 		.lddfr = LDDFR_PKF_RGB24,
407802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
417802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
427802ca6bSGeert Uytterhoeven 			    LDBBSIFR_SWPB | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24,
4311696c5eSBiju Das 	}, {
4411696c5eSBiju Das 		.fourcc = DRM_FORMAT_ARGB8888,
4511696c5eSBiju Das 		.bpp = 32,
4611696c5eSBiju Das 		.lddfr = LDDFR_PKF_ARGB32,
477802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS,
487802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_PK | LDBBSIFR_SWPL | LDBBSIFR_RY |
497802ca6bSGeert Uytterhoeven 			    LDBBSIFR_RPKF_ARGB32,
5011696c5eSBiju Das 	}, {
5111696c5eSBiju Das 		.fourcc = DRM_FORMAT_XRGB8888,
5211696c5eSBiju Das 		.bpp = 32,
5311696c5eSBiju Das 		.lddfr = LDDFR_PKF_ARGB32,
547802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS,
557802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_RY |
567802ca6bSGeert Uytterhoeven 			    LDBBSIFR_RPKF_ARGB32,
5711696c5eSBiju Das 	}, {
5811696c5eSBiju Das 		.fourcc = DRM_FORMAT_NV12,
5911696c5eSBiju Das 		.bpp = 12,
6011696c5eSBiju Das 		.lddfr = LDDFR_CC | LDDFR_YF_420,
617802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
627802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
637802ca6bSGeert Uytterhoeven 			    LDBBSIFR_SWPB | LDBBSIFR_CHRR_420,
6411696c5eSBiju Das 	}, {
6511696c5eSBiju Das 		.fourcc = DRM_FORMAT_NV21,
6611696c5eSBiju Das 		.bpp = 12,
6711696c5eSBiju Das 		.lddfr = LDDFR_CC | LDDFR_YF_420,
687802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS | LDDDSR_WS,
697802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
707802ca6bSGeert Uytterhoeven 			    LDBBSIFR_CHRR_420,
7111696c5eSBiju Das 	}, {
7211696c5eSBiju Das 		.fourcc = DRM_FORMAT_NV16,
7311696c5eSBiju Das 		.bpp = 16,
7411696c5eSBiju Das 		.lddfr = LDDFR_CC | LDDFR_YF_422,
757802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
767802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
777802ca6bSGeert Uytterhoeven 			    LDBBSIFR_SWPB | LDBBSIFR_CHRR_422,
7811696c5eSBiju Das 	}, {
7911696c5eSBiju Das 		.fourcc = DRM_FORMAT_NV61,
8011696c5eSBiju Das 		.bpp = 16,
8111696c5eSBiju Das 		.lddfr = LDDFR_CC | LDDFR_YF_422,
827802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS | LDDDSR_WS,
837802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
847802ca6bSGeert Uytterhoeven 			    LDBBSIFR_CHRR_422,
8511696c5eSBiju Das 	}, {
8611696c5eSBiju Das 		.fourcc = DRM_FORMAT_NV24,
8711696c5eSBiju Das 		.bpp = 24,
8811696c5eSBiju Das 		.lddfr = LDDFR_CC | LDDFR_YF_444,
897802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
907802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
917802ca6bSGeert Uytterhoeven 			    LDBBSIFR_SWPB | LDBBSIFR_CHRR_444,
9211696c5eSBiju Das 	}, {
9311696c5eSBiju Das 		.fourcc = DRM_FORMAT_NV42,
9411696c5eSBiju Das 		.bpp = 24,
9511696c5eSBiju Das 		.lddfr = LDDFR_CC | LDDFR_YF_444,
967802ca6bSGeert Uytterhoeven 		.ldddsr = LDDDSR_LS | LDDDSR_WS,
977802ca6bSGeert Uytterhoeven 		.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
987802ca6bSGeert Uytterhoeven 			    LDBBSIFR_CHRR_444,
9911696c5eSBiju Das 	},
10011696c5eSBiju Das };
10111696c5eSBiju Das 
shmob_drm_format_info(u32 fourcc)10211696c5eSBiju Das const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc)
10311696c5eSBiju Das {
10411696c5eSBiju Das 	unsigned int i;
10511696c5eSBiju Das 
10611696c5eSBiju Das 	for (i = 0; i < ARRAY_SIZE(shmob_drm_format_infos); ++i) {
10711696c5eSBiju Das 		if (shmob_drm_format_infos[i].fourcc == fourcc)
10811696c5eSBiju Das 			return &shmob_drm_format_infos[i];
10911696c5eSBiju Das 	}
11011696c5eSBiju Das 
11111696c5eSBiju Das 	return NULL;
11211696c5eSBiju Das }
11311696c5eSBiju Das 
11411696c5eSBiju Das /* -----------------------------------------------------------------------------
11511696c5eSBiju Das  * Frame buffer
11611696c5eSBiju Das  */
11711696c5eSBiju Das 
11811696c5eSBiju Das static struct drm_framebuffer *
shmob_drm_fb_create(struct drm_device * dev,struct drm_file * file_priv,const struct drm_mode_fb_cmd2 * mode_cmd)11911696c5eSBiju Das shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
12011696c5eSBiju Das 		    const struct drm_mode_fb_cmd2 *mode_cmd)
12111696c5eSBiju Das {
12211696c5eSBiju Das 	const struct shmob_drm_format_info *format;
12311696c5eSBiju Das 
12411696c5eSBiju Das 	format = shmob_drm_format_info(mode_cmd->pixel_format);
12511696c5eSBiju Das 	if (format == NULL) {
12611696c5eSBiju Das 		dev_dbg(dev->dev, "unsupported pixel format %p4cc\n",
12711696c5eSBiju Das 			&mode_cmd->pixel_format);
12811696c5eSBiju Das 		return ERR_PTR(-EINVAL);
12911696c5eSBiju Das 	}
13011696c5eSBiju Das 
13111696c5eSBiju Das 	if (mode_cmd->pitches[0] & 7 || mode_cmd->pitches[0] >= 65536) {
13211696c5eSBiju Das 		dev_dbg(dev->dev, "invalid pitch value %u\n",
13311696c5eSBiju Das 			mode_cmd->pitches[0]);
13411696c5eSBiju Das 		return ERR_PTR(-EINVAL);
13511696c5eSBiju Das 	}
13611696c5eSBiju Das 
1377802ca6bSGeert Uytterhoeven 	if (shmob_drm_format_is_yuv(format)) {
13811696c5eSBiju Das 		unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;
13911696c5eSBiju Das 
14011696c5eSBiju Das 		if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {
14111696c5eSBiju Das 			dev_dbg(dev->dev,
14211696c5eSBiju Das 				"luma and chroma pitches do not match\n");
14311696c5eSBiju Das 			return ERR_PTR(-EINVAL);
14411696c5eSBiju Das 		}
14511696c5eSBiju Das 	}
14611696c5eSBiju Das 
14711696c5eSBiju Das 	return drm_gem_fb_create(dev, file_priv, mode_cmd);
14811696c5eSBiju Das }
14911696c5eSBiju Das 
15011696c5eSBiju Das static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {
15111696c5eSBiju Das 	.fb_create = shmob_drm_fb_create,
152*4afa0410SGeert Uytterhoeven 	.atomic_check = drm_atomic_helper_check,
153*4afa0410SGeert Uytterhoeven 	.atomic_commit = drm_atomic_helper_commit,
15411696c5eSBiju Das };
15511696c5eSBiju Das 
shmob_drm_modeset_init(struct shmob_drm_device * sdev)15611696c5eSBiju Das int shmob_drm_modeset_init(struct shmob_drm_device *sdev)
15711696c5eSBiju Das {
158*4afa0410SGeert Uytterhoeven 	struct drm_device *dev = &sdev->ddev;
15911696c5eSBiju Das 	int ret;
16011696c5eSBiju Das 
161*4afa0410SGeert Uytterhoeven 	ret = drmm_mode_config_init(dev);
16211696c5eSBiju Das 	if (ret)
16311696c5eSBiju Das 		return ret;
16411696c5eSBiju Das 
16595478b08SGeert Uytterhoeven 	ret = shmob_drm_crtc_create(sdev);
16695478b08SGeert Uytterhoeven 	if (ret < 0)
16795478b08SGeert Uytterhoeven 		return ret;
16895478b08SGeert Uytterhoeven 
16995478b08SGeert Uytterhoeven 	ret = shmob_drm_encoder_create(sdev);
17095478b08SGeert Uytterhoeven 	if (ret < 0)
17195478b08SGeert Uytterhoeven 		return ret;
17295478b08SGeert Uytterhoeven 
17395478b08SGeert Uytterhoeven 	ret = shmob_drm_connector_create(sdev, &sdev->encoder);
17495478b08SGeert Uytterhoeven 	if (ret < 0)
17595478b08SGeert Uytterhoeven 		return ret;
17611696c5eSBiju Das 
177*4afa0410SGeert Uytterhoeven 	drm_mode_config_reset(dev);
178*4afa0410SGeert Uytterhoeven 
179*4afa0410SGeert Uytterhoeven 	drm_kms_helper_poll_init(dev);
18011696c5eSBiju Das 
1815417750dSGeert Uytterhoeven 	sdev->ddev.mode_config.min_width = 0;
1825417750dSGeert Uytterhoeven 	sdev->ddev.mode_config.min_height = 0;
1835417750dSGeert Uytterhoeven 	sdev->ddev.mode_config.max_width = 4095;
1845417750dSGeert Uytterhoeven 	sdev->ddev.mode_config.max_height = 4095;
1855417750dSGeert Uytterhoeven 	sdev->ddev.mode_config.funcs = &shmob_drm_mode_config_funcs;
18611696c5eSBiju Das 
18711696c5eSBiju Das 	return 0;
18811696c5eSBiju Das }
189