Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * shmob_drm_kms.c  --  SH Mobile DRM Mode Setting
0004  *
0005  * Copyright (C) 2012 Renesas Electronics Corporation
0006  *
0007  * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
0008  */
0009 
0010 #include <drm/drm_crtc.h>
0011 #include <drm/drm_crtc_helper.h>
0012 #include <drm/drm_fb_cma_helper.h>
0013 #include <drm/drm_fourcc.h>
0014 #include <drm/drm_gem_cma_helper.h>
0015 #include <drm/drm_gem_framebuffer_helper.h>
0016 #include <drm/drm_probe_helper.h>
0017 
0018 #include "shmob_drm_crtc.h"
0019 #include "shmob_drm_drv.h"
0020 #include "shmob_drm_kms.h"
0021 #include "shmob_drm_regs.h"
0022 
0023 /* -----------------------------------------------------------------------------
0024  * Format helpers
0025  */
0026 
0027 static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
0028     {
0029         .fourcc = DRM_FORMAT_RGB565,
0030         .bpp = 16,
0031         .yuv = false,
0032         .lddfr = LDDFR_PKF_RGB16,
0033     }, {
0034         .fourcc = DRM_FORMAT_RGB888,
0035         .bpp = 24,
0036         .yuv = false,
0037         .lddfr = LDDFR_PKF_RGB24,
0038     }, {
0039         .fourcc = DRM_FORMAT_ARGB8888,
0040         .bpp = 32,
0041         .yuv = false,
0042         .lddfr = LDDFR_PKF_ARGB32,
0043     }, {
0044         .fourcc = DRM_FORMAT_NV12,
0045         .bpp = 12,
0046         .yuv = true,
0047         .lddfr = LDDFR_CC | LDDFR_YF_420,
0048     }, {
0049         .fourcc = DRM_FORMAT_NV21,
0050         .bpp = 12,
0051         .yuv = true,
0052         .lddfr = LDDFR_CC | LDDFR_YF_420,
0053     }, {
0054         .fourcc = DRM_FORMAT_NV16,
0055         .bpp = 16,
0056         .yuv = true,
0057         .lddfr = LDDFR_CC | LDDFR_YF_422,
0058     }, {
0059         .fourcc = DRM_FORMAT_NV61,
0060         .bpp = 16,
0061         .yuv = true,
0062         .lddfr = LDDFR_CC | LDDFR_YF_422,
0063     }, {
0064         .fourcc = DRM_FORMAT_NV24,
0065         .bpp = 24,
0066         .yuv = true,
0067         .lddfr = LDDFR_CC | LDDFR_YF_444,
0068     }, {
0069         .fourcc = DRM_FORMAT_NV42,
0070         .bpp = 24,
0071         .yuv = true,
0072         .lddfr = LDDFR_CC | LDDFR_YF_444,
0073     },
0074 };
0075 
0076 const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc)
0077 {
0078     unsigned int i;
0079 
0080     for (i = 0; i < ARRAY_SIZE(shmob_drm_format_infos); ++i) {
0081         if (shmob_drm_format_infos[i].fourcc == fourcc)
0082             return &shmob_drm_format_infos[i];
0083     }
0084 
0085     return NULL;
0086 }
0087 
0088 /* -----------------------------------------------------------------------------
0089  * Frame buffer
0090  */
0091 
0092 static struct drm_framebuffer *
0093 shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
0094             const struct drm_mode_fb_cmd2 *mode_cmd)
0095 {
0096     const struct shmob_drm_format_info *format;
0097 
0098     format = shmob_drm_format_info(mode_cmd->pixel_format);
0099     if (format == NULL) {
0100         dev_dbg(dev->dev, "unsupported pixel format %08x\n",
0101             mode_cmd->pixel_format);
0102         return ERR_PTR(-EINVAL);
0103     }
0104 
0105     if (mode_cmd->pitches[0] & 7 || mode_cmd->pitches[0] >= 65536) {
0106         dev_dbg(dev->dev, "invalid pitch value %u\n",
0107             mode_cmd->pitches[0]);
0108         return ERR_PTR(-EINVAL);
0109     }
0110 
0111     if (format->yuv) {
0112         unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;
0113 
0114         if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {
0115             dev_dbg(dev->dev,
0116                 "luma and chroma pitches do not match\n");
0117             return ERR_PTR(-EINVAL);
0118         }
0119     }
0120 
0121     return drm_gem_fb_create(dev, file_priv, mode_cmd);
0122 }
0123 
0124 static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {
0125     .fb_create = shmob_drm_fb_create,
0126 };
0127 
0128 int shmob_drm_modeset_init(struct shmob_drm_device *sdev)
0129 {
0130     int ret;
0131 
0132     ret = drmm_mode_config_init(sdev->ddev);
0133     if (ret)
0134         return ret;
0135 
0136     shmob_drm_crtc_create(sdev);
0137     shmob_drm_encoder_create(sdev);
0138     shmob_drm_connector_create(sdev, &sdev->encoder.encoder);
0139 
0140     drm_kms_helper_poll_init(sdev->ddev);
0141 
0142     sdev->ddev->mode_config.min_width = 0;
0143     sdev->ddev->mode_config.min_height = 0;
0144     sdev->ddev->mode_config.max_width = 4095;
0145     sdev->ddev->mode_config.max_height = 4095;
0146     sdev->ddev->mode_config.funcs = &shmob_drm_mode_config_funcs;
0147 
0148     drm_helper_disable_unused_functions(sdev->ddev);
0149 
0150     return 0;
0151 }