linux/drivers/gpu/drm/shmobile/shmob_drm_kms.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * shmob_drm_kms.c  --  SH Mobile DRM Mode Setting
   4 *
   5 * Copyright (C) 2012 Renesas Electronics Corporation
   6 *
   7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
   8 */
   9
  10#include <drm/drmP.h>
  11#include <drm/drm_crtc.h>
  12#include <drm/drm_crtc_helper.h>
  13#include <drm/drm_fb_cma_helper.h>
  14#include <drm/drm_gem_cma_helper.h>
  15#include <drm/drm_gem_framebuffer_helper.h>
  16#include <drm/drm_probe_helper.h>
  17
  18#include "shmob_drm_crtc.h"
  19#include "shmob_drm_drv.h"
  20#include "shmob_drm_kms.h"
  21#include "shmob_drm_regs.h"
  22
  23/* -----------------------------------------------------------------------------
  24 * Format helpers
  25 */
  26
  27static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
  28        {
  29                .fourcc = DRM_FORMAT_RGB565,
  30                .bpp = 16,
  31                .yuv = false,
  32                .lddfr = LDDFR_PKF_RGB16,
  33        }, {
  34                .fourcc = DRM_FORMAT_RGB888,
  35                .bpp = 24,
  36                .yuv = false,
  37                .lddfr = LDDFR_PKF_RGB24,
  38        }, {
  39                .fourcc = DRM_FORMAT_ARGB8888,
  40                .bpp = 32,
  41                .yuv = false,
  42                .lddfr = LDDFR_PKF_ARGB32,
  43        }, {
  44                .fourcc = DRM_FORMAT_NV12,
  45                .bpp = 12,
  46                .yuv = true,
  47                .lddfr = LDDFR_CC | LDDFR_YF_420,
  48        }, {
  49                .fourcc = DRM_FORMAT_NV21,
  50                .bpp = 12,
  51                .yuv = true,
  52                .lddfr = LDDFR_CC | LDDFR_YF_420,
  53        }, {
  54                .fourcc = DRM_FORMAT_NV16,
  55                .bpp = 16,
  56                .yuv = true,
  57                .lddfr = LDDFR_CC | LDDFR_YF_422,
  58        }, {
  59                .fourcc = DRM_FORMAT_NV61,
  60                .bpp = 16,
  61                .yuv = true,
  62                .lddfr = LDDFR_CC | LDDFR_YF_422,
  63        }, {
  64                .fourcc = DRM_FORMAT_NV24,
  65                .bpp = 24,
  66                .yuv = true,
  67                .lddfr = LDDFR_CC | LDDFR_YF_444,
  68        }, {
  69                .fourcc = DRM_FORMAT_NV42,
  70                .bpp = 24,
  71                .yuv = true,
  72                .lddfr = LDDFR_CC | LDDFR_YF_444,
  73        },
  74};
  75
  76const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc)
  77{
  78        unsigned int i;
  79
  80        for (i = 0; i < ARRAY_SIZE(shmob_drm_format_infos); ++i) {
  81                if (shmob_drm_format_infos[i].fourcc == fourcc)
  82                        return &shmob_drm_format_infos[i];
  83        }
  84
  85        return NULL;
  86}
  87
  88/* -----------------------------------------------------------------------------
  89 * Frame buffer
  90 */
  91
  92static struct drm_framebuffer *
  93shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
  94                    const struct drm_mode_fb_cmd2 *mode_cmd)
  95{
  96        const struct shmob_drm_format_info *format;
  97
  98        format = shmob_drm_format_info(mode_cmd->pixel_format);
  99        if (format == NULL) {
 100                dev_dbg(dev->dev, "unsupported pixel format %08x\n",
 101                        mode_cmd->pixel_format);
 102                return ERR_PTR(-EINVAL);
 103        }
 104
 105        if (mode_cmd->pitches[0] & 7 || mode_cmd->pitches[0] >= 65536) {
 106                dev_dbg(dev->dev, "invalid pitch value %u\n",
 107                        mode_cmd->pitches[0]);
 108                return ERR_PTR(-EINVAL);
 109        }
 110
 111        if (format->yuv) {
 112                unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;
 113
 114                if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {
 115                        dev_dbg(dev->dev,
 116                                "luma and chroma pitches do not match\n");
 117                        return ERR_PTR(-EINVAL);
 118                }
 119        }
 120
 121        return drm_gem_fb_create(dev, file_priv, mode_cmd);
 122}
 123
 124static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {
 125        .fb_create = shmob_drm_fb_create,
 126};
 127
 128int shmob_drm_modeset_init(struct shmob_drm_device *sdev)
 129{
 130        drm_mode_config_init(sdev->ddev);
 131
 132        shmob_drm_crtc_create(sdev);
 133        shmob_drm_encoder_create(sdev);
 134        shmob_drm_connector_create(sdev, &sdev->encoder.encoder);
 135
 136        drm_kms_helper_poll_init(sdev->ddev);
 137
 138        sdev->ddev->mode_config.min_width = 0;
 139        sdev->ddev->mode_config.min_height = 0;
 140        sdev->ddev->mode_config.max_width = 4095;
 141        sdev->ddev->mode_config.max_height = 4095;
 142        sdev->ddev->mode_config.funcs = &shmob_drm_mode_config_funcs;
 143
 144        drm_helper_disable_unused_functions(sdev->ddev);
 145
 146        return 0;
 147}
 148