From a2f0216f5247f5034952eadcd1c230ead6f20e33 Mon Sep 17 00:00:00 2001 From: yzq Date: Mon, 7 Apr 2014 15:33:43 +0800 Subject: [PATCH] rk3288 chromium: update for hdmi display --- arch/arm/configs/rockchip_chromium_defconfig | 4 +- drivers/gpu/drm/rockchip/Kconfig | 3 +- drivers/gpu/drm/rockchip/Makefile | 6 +- .../gpu/drm/rockchip/rockchip_drm_connector.c | 52 ++ drivers/gpu/drm/rockchip/rockchip_drm_core.c | 6 - drivers/gpu/drm/rockchip/rockchip_drm_crtc.c | 24 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 20 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 + .../gpu/drm/rockchip/rockchip_drm_encoder.c | 27 + .../gpu/drm/rockchip/rockchip_drm_extend.c | 872 ++++++++++++++++++ .../gpu/drm/rockchip/rockchip_drm_extend.h | 37 + drivers/gpu/drm/rockchip/rockchip_drm_plane.c | 2 + .../gpu/drm/rockchip/rockchip_drm_primary.c | 41 +- drivers/video/rockchip/hdmi/Kconfig | 2 +- drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c | 6 + drivers/video/rockchip/lcdc/rk3288_lcdc.c | 3 + drivers/video/rockchip/rk_drm_fb.c | 228 ++++- drivers/video/rockchip/rk_drm_fb.h | 12 +- include/linux/rk_fb.h | 3 + 19 files changed, 1301 insertions(+), 50 deletions(-) create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_extend.c create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_extend.h diff --git a/arch/arm/configs/rockchip_chromium_defconfig b/arch/arm/configs/rockchip_chromium_defconfig index 33f1fbf84ead..c853a5366586 100644 --- a/arch/arm/configs/rockchip_chromium_defconfig +++ b/arch/arm/configs/rockchip_chromium_defconfig @@ -331,7 +331,8 @@ CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_DRM=y CONFIG_DRM_ROCKCHIP=y CONFIG_DRM_ROCKCHIP_DMABUF=y -CONFIG_DRM_RK_PRIMARY=y +CONFIG_DRM_ROCKCHIP_PRIMARY=y +CONFIG_DRM_ROCKCHIP_HDMI=y CONFIG_MALI_T6XX=y CONFIG_MALI_T6XX_DVFS=y CONFIG_MALI_T6XX_RT_PM=y @@ -347,6 +348,7 @@ CONFIG_BACKLIGHT_PWM=y CONFIG_LCDC_RK3288=y CONFIG_RK_TRSM=y CONFIG_RK32_LVDS=y +CONFIG_RK_HDMI=y CONFIG_ROCKCHIP_RGA2=y # CONFIG_IEP is not set CONFIG_LOGO=y diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index f38aa4224200..6e08c3b18913 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -22,13 +22,14 @@ config DRM_ROCKCHIP_DMABUF help Choose this option if you want to use DMABUF feature for DRM. -config DRM_RK_PRIMARY +config DRM_ROCKCHIP_PRIMARY bool "RK DRM PRIMARY" depends on OF && DRM_ROCKCHIP select FB_MODE_HELPERS select VIDEOMODE_HELPERS help Choose this option if you want to use Rockchip PRIMARY DISPLAY for DRM. + config DRM_ROCKCHIP_HDMI bool "Rockchip DRM HDMI" depends on DRM_ROCKCHIP diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index 99aba1a9a093..cb46f9e855d3 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -10,10 +10,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_encoder.o rockchip_drm_connecto rockchipdrm-$(CONFIG_DRM_ROCKCHIP_IOMMU) += rockchip_drm_iommu.o rockchipdrm-$(CONFIG_DRM_ROCKCHIP_DMABUF) += rockchip_drm_dmabuf.o -rockchipdrm-$(CONFIG_DRM_RK_PRIMARY) += rockchip_drm_primary.o -rockchipdrm-$(CONFIG_DRM_ROCKCHIP_HDMI) += rockchip_hdmi.o rockchip_mixer.o \ - rockchip_ddc.o rockchip_hdmiphy.o \ - rockchip_drm_hdmi.o +rockchipdrm-$(CONFIG_DRM_ROCKCHIP_PRIMARY) += rockchip_drm_primary.o +rockchipdrm-$(CONFIG_DRM_ROCKCHIP_HDMI) += rockchip_drm_extend.o rockchipdrm-$(CONFIG_DRM_ROCKCHIP_VIDI) += rockchip_drm_vidi.o obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_connector.c b/drivers/gpu/drm/rockchip/rockchip_drm_connector.c index c3d5119a386a..f205aa8bad50 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_connector.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_connector.c @@ -57,7 +57,31 @@ convert_to_display_mode(struct drm_display_mode *mode, if (timing->vmode & FB_VMODE_DOUBLE) mode->flags |= DRM_MODE_FLAG_DBLSCAN; } +static inline void +convert_fbmode_to_display_mode(struct drm_display_mode *mode, + struct fb_videomode *timing) +{ + DRM_DEBUG_KMS("%s\n", __FILE__); + + mode->clock = timing->pixclock / 1000; + mode->vrefresh = timing->refresh; + mode->hdisplay = timing->xres; + mode->hsync_start = mode->hdisplay + timing->right_margin; + mode->hsync_end = mode->hsync_start + timing->hsync_len; + mode->htotal = mode->hsync_end + timing->left_margin; + + mode->vdisplay = timing->yres; + mode->vsync_start = mode->vdisplay + timing->lower_margin; + mode->vsync_end = mode->vsync_start + timing->vsync_len; + mode->vtotal = mode->vsync_end + timing->upper_margin; + + if (timing->vmode & FB_VMODE_INTERLACED) + mode->flags |= DRM_MODE_FLAG_INTERLACE; + + if (timing->vmode & FB_VMODE_DOUBLE) + mode->flags |= DRM_MODE_FLAG_DBLSCAN; +} /* convert drm_display_mode to rockchip_video_timings */ static inline void convert_to_video_timing(struct fb_videomode *timing, @@ -130,6 +154,34 @@ static int rockchip_drm_connector_get_modes(struct drm_connector *connector) } drm_mode_connector_update_edid_property(connector, edid); + } else if(display_ops->get_modelist){ + struct list_head *pos,*head; + struct fb_modelist *modelist; + struct fb_videomode *mode; + struct drm_display_mode *disp_mode = NULL; + count=0; + head = display_ops->get_modelist(manager->dev); + + list_for_each(pos,head){ + modelist = list_entry(pos, struct fb_modelist, list); + mode = &modelist->mode; + disp_mode = drm_mode_create(connector->dev); + if (!mode) { + DRM_ERROR("failed to create a new display mode.\n"); + return count; + } + convert_fbmode_to_display_mode(disp_mode, mode); + + if(mode->xres == 1280 && mode->yres == 720 && mode->refresh == 60) + disp_mode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_set_name(disp_mode); +// snprintf(disp_mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s-%d", +// disp_mode->hdisplay, disp_mode->vdisplay, +// !!(disp_mode->flags & DRM_MODE_FLAG_INTERLACE)? "i" : "p",disp_mode->vrefresh); + drm_mode_probed_add(connector, disp_mode); + count++; + } } else { struct rockchip_drm_panel_info *panel; struct drm_display_mode *mode = drm_mode_create(connector->dev); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_core.c b/drivers/gpu/drm/rockchip/rockchip_drm_core.c index 3e9b946cf4e4..393ff82f3357 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_core.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_core.c @@ -28,7 +28,6 @@ static int rockchip_drm_create_enc_conn(struct drm_device *dev, DRM_DEBUG_DRIVER("%s\n", __FILE__); - printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__); subdrv->manager->dev = subdrv->dev; /* create and initialize a encoder for this sub driver. */ @@ -116,15 +115,12 @@ int rockchip_drm_device_register(struct drm_device *dev) DRM_DEBUG_DRIVER("%s\n", __FILE__); - printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__); if (!dev) return -EINVAL; - printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__); list_for_each_entry_safe(subdrv, n, &rockchip_drm_subdrv_list, list) { err = rockchip_drm_subdrv_probe(dev, subdrv); if (err) { - printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__); DRM_DEBUG("rockchip drm subdrv probe failed.\n"); list_del(&subdrv->list); continue; @@ -141,7 +137,6 @@ int rockchip_drm_device_register(struct drm_device *dev) err = rockchip_drm_create_enc_conn(dev, subdrv); if (err) { - printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__); DRM_DEBUG("failed to create encoder and connector.\n"); rockchip_drm_subdrv_remove(dev, subdrv); list_del(&subdrv->list); @@ -151,7 +146,6 @@ int rockchip_drm_device_register(struct drm_device *dev) fine_cnt++; } - printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__); if (!fine_cnt) return -EINVAL; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_crtc.c b/drivers/gpu/drm/rockchip/rockchip_drm_crtc.c index 90b3ea956f76..b02deebdbdfc 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_crtc.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_crtc.c @@ -54,7 +54,7 @@ static void rockchip_drm_crtc_dpms(struct drm_crtc *crtc, int mode) { struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc); - DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); +// printk(KERN_ERR"crtc[%d] mode[%d]\n", crtc->base.id, mode); if (rockchip_crtc->dpms == mode) { DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); @@ -147,11 +147,11 @@ static int rockchip_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, int ret; DRM_DEBUG_KMS("%s\n", __FILE__); - + /* when framebuffer changing is requested, crtc's dpms should be on */ if (rockchip_crtc->dpms > DRM_MODE_DPMS_ON) { DRM_ERROR("failed framebuffer changing request.\n"); - return -EPERM; +// return -EPERM; } crtc_w = crtc->fb->width - x; @@ -204,6 +204,7 @@ static int rockchip_drm_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *old_fb = crtc->fb; int ret = -EINVAL; + DRM_DEBUG_KMS("%s\n", __FILE__); /* when the page flip is requested, crtc's dpms should be on */ @@ -370,7 +371,24 @@ int rockchip_drm_crtc_create(struct drm_device *dev, unsigned int nr) return 0; } +#if 0 +int rockchip_get_crtc_vblank_timestamp(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags) +{ + struct rockchip_drm_private *private = dev->dev_private; + struct rockchip_drm_crtc *rockchip_crtc = + to_rockchip_crtc(private->crtc[crtc]); + + if (rockchip_crtc->dpms != DRM_MODE_DPMS_ON) + return -EPERM; + rockchip_drm_fn_encoder(private->crtc[crtc], &crtc, + rockchip_get_vblank_timestamp); + +} +#endif int rockchip_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) { struct rockchip_drm_private *private = dev->dev_private; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 0c7923491fe5..eeb8d08f2262 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -252,6 +252,7 @@ static struct drm_driver rockchip_drm_driver = { .get_vblank_counter = drm_vblank_count, .enable_vblank = rockchip_drm_crtc_enable_vblank, .disable_vblank = rockchip_drm_crtc_disable_vblank, +// .get_vblank_timestamp = rockchip_get_crtc_vblank_timestamp, .gem_init_object = rockchip_drm_gem_init_object, .gem_free_object = rockchip_drm_gem_free_object, .gem_vm_ops = &rockchip_drm_gem_vm_ops, @@ -306,13 +307,20 @@ static int __init rockchip_drm_init(void) DRM_DEBUG_DRIVER("%s\n", __FILE__); -#ifdef CONFIG_DRM_RK_PRIMARY +#ifdef CONFIG_DRM_ROCKCHIP_PRIMARY ret = platform_driver_register(&primary_platform_driver); if (ret < 0) - goto out_fimd; + goto out_primary; platform_device_register_simple("primary-display", -1, NULL, 0); #endif +#ifdef CONFIG_DRM_ROCKCHIP_HDMI + ret = platform_driver_register(&extend_platform_driver); + if (ret < 0) + goto out_extend; + platform_device_register_simple("extend-display", -1, + NULL, 0); +#endif ret = platform_driver_register(&rockchip_drm_platform_driver); if (ret < 0) @@ -331,9 +339,13 @@ static int __init rockchip_drm_init(void) out: platform_driver_unregister(&rockchip_drm_platform_driver); out_drm: -#ifdef CONFIG_DRM_RK_PRIMARY +#ifdef CONFIG_DRM_ROCKCHIP_PRIMARY platform_driver_unregister(&primary_platform_driver); -out_fimd: +out_primary: +#endif +#ifdef CONFIG_DRM_ROCKCHIP_HDMI + platform_driver_unregister(&extend_platform_driver); +out_extend: #endif return ret; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index d0d63cfe8410..96072670f880 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -117,6 +117,7 @@ struct rockchip_drm_overlay { unsigned int mode_width; unsigned int mode_height; unsigned int refresh; + unsigned int pixclock; unsigned int scan_flag; unsigned int bpp; unsigned int pitch; @@ -149,6 +150,7 @@ struct rockchip_drm_display_ops { struct edid *(*get_edid)(struct device *dev, struct drm_connector *connector); void *(*get_panel)(struct device *dev); + void *(*get_modelist)(struct device *dev); int (*check_timing)(struct device *dev, void *timing); int (*power_on)(struct device *dev, int mode); }; @@ -338,6 +340,7 @@ int rockchip_platform_device_ipp_register(void); void rockchip_platform_device_ipp_unregister(void); extern struct platform_driver primary_platform_driver; +extern struct platform_driver extend_platform_driver; extern struct platform_driver hdmi_driver; extern struct platform_driver mixer_driver; extern struct platform_driver rockchip_drm_common_hdmi_driver; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_encoder.c b/drivers/gpu/drm/rockchip/rockchip_drm_encoder.c index 671267bf39b0..8ec2f30d8b95 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_encoder.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_encoder.c @@ -389,7 +389,34 @@ void rockchip_drm_fn_encoder(struct drm_crtc *crtc, void *data, fn(encoder, data); } } +int rockchip_get_crtc_vblank_timestamp(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags) +{ +#if 0 + ktime_t stime, etime, mono_time_offset; + struct timeval tv_etime; + struct drm_display_mode *mode; + int vbl_status, vtotal, vdisplay; + int vpos, hpos, i; + s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; + bool invbl; + + if (crtc < 0 || crtc >= dev->num_crtcs) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + /* Scanout position query not supported? Should not happen. */ + if (!dev->driver->get_scanout_position) { + DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); + return -EIO; + } +#endif + return 0;//vbl_status; + +} void rockchip_drm_enable_vblank(struct drm_encoder *encoder, void *data) { struct rockchip_drm_manager *manager = diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_extend.c b/drivers/gpu/drm/rockchip/rockchip_drm_extend.c new file mode 100644 index 000000000000..677e859e450b --- /dev/null +++ b/drivers/gpu/drm/rockchip/rockchip_drm_extend.c @@ -0,0 +1,872 @@ +/* + * rk3288_drm_fimd.c + * + * Copyright (C) ROCKCHIP, Inc. + * Author:yzq + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include