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