mirror of
https://github.com/hardkernel/linux.git
synced 2026-04-10 15:08:06 +09:00
rk3288 chromium: update for hdmi display
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 =
|
||||
|
||||
872
drivers/gpu/drm/rockchip/rockchip_drm_extend.c
Normal file
872
drivers/gpu/drm/rockchip/rockchip_drm_extend.c
Normal file
@@ -0,0 +1,872 @@
|
||||
/*
|
||||
* rk3288_drm_fimd.c
|
||||
*
|
||||
* Copyright (C) ROCKCHIP, Inc.
|
||||
* Author:yzq<yzq@rock-chips.com>
|
||||
* 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 <drm/drmP.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
#include <video/of_display_timing.h>
|
||||
#include <drm/rockchip_drm.h>
|
||||
#include <linux/rockchip/cpu.h>
|
||||
#include <linux/rockchip/iomap.h>
|
||||
#include <linux/rk_fb.h>
|
||||
#include <video/display_timing.h>
|
||||
#include <linux/rockchip/cpu.h>
|
||||
#include <linux/rockchip/iomap.h>
|
||||
#include <linux/rockchip/grf.h>
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_fbdev.h"
|
||||
#include "rockchip_drm_crtc.h"
|
||||
#include "rockchip_drm_iommu.h"
|
||||
#include "rockchip_drm_extend.h"
|
||||
static struct device *g_dev = NULL;
|
||||
static int extend_activate(struct extend_context *ctx, bool enable);
|
||||
#if 0
|
||||
extern struct void *get_extend_drv(void);
|
||||
#endif
|
||||
#if 0
|
||||
static const char fake_edid_info[] = {
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05,
|
||||
0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78,
|
||||
0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd,
|
||||
0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00,
|
||||
0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e,
|
||||
0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
|
||||
0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18,
|
||||
0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1,
|
||||
0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83,
|
||||
0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00,
|
||||
0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c,
|
||||
0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a,
|
||||
0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00,
|
||||
0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
|
||||
0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x06
|
||||
};
|
||||
#endif
|
||||
extern int primary_is_display;
|
||||
extern wait_queue_head_t wait_primary_queue;
|
||||
static bool extend_display_is_connected(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
|
||||
return drm_disp->is_connected?true:false;
|
||||
|
||||
/* TODO. */
|
||||
}
|
||||
|
||||
static void *extend_get_panel(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
struct list_head *pos;
|
||||
struct fb_modelist *modelist;
|
||||
struct fb_videomode *mode;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
if(!drm_disp->is_connected)
|
||||
return NULL;
|
||||
list_for_each(pos,drm_disp->modelist){
|
||||
modelist = list_entry(pos, struct fb_modelist, list);
|
||||
mode = &modelist->mode;
|
||||
if(mode->flag == HDMI_VIDEO_DEFAULT_MODE)
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&ctx->panel->timing,mode,sizeof(struct fb_videomode));
|
||||
|
||||
return ctx->panel;
|
||||
}
|
||||
static void *extend_get_modelist(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
|
||||
return drm_disp->modelist;
|
||||
}
|
||||
static int extend_check_timing(struct device *dev, void *timing)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
/* TODO. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int extend_display_power_on(struct device *dev, int mode)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
/* TODO */
|
||||
printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
extend_activate(ctx,mode == DRM_MODE_DPMS_ON?true:false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
struct edid *extend_get_edid(struct device *dev,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
#if 0
|
||||
int i, j = 0, valid_extensions = 0;
|
||||
struct hdmi *hdmi = get_extend_drv();
|
||||
u8 *block, *new;
|
||||
struct edid *edid = NULL;
|
||||
struct edid *raw_edid = NULL;
|
||||
bool print_bad_edid = !connector->bad_edid_counter;
|
||||
|
||||
if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
|
||||
return NULL;
|
||||
/* base block fetch */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if(hdmi->read_edid(hdmi, 0, block))
|
||||
goto out;
|
||||
if (drm_edid_block_valid(block, 0, print_bad_edid))
|
||||
break;
|
||||
}
|
||||
if (i == 4)
|
||||
goto carp;
|
||||
|
||||
/* if there's no extensions, we're done */
|
||||
if (block[0x7e] == 0)
|
||||
return block;
|
||||
|
||||
new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
|
||||
if (!new)
|
||||
goto out;
|
||||
block = new;
|
||||
|
||||
for (j = 1; j <= block[0x7e]; j++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if(hdmi->read_edid(hdmi, j, block))
|
||||
goto out;
|
||||
if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) {
|
||||
valid_extensions++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 4 && print_bad_edid) {
|
||||
dev_warn(connector->dev->dev,
|
||||
"%s: Ignoring invalid EDID block %d.\n",
|
||||
drm_get_connector_name(connector), j);
|
||||
|
||||
connector->bad_edid_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_extensions != block[0x7e]) {
|
||||
block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
|
||||
block[0x7e] = valid_extensions;
|
||||
new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
|
||||
if (!new)
|
||||
goto out;
|
||||
block = new;
|
||||
}
|
||||
edid = (struct edid *)block;
|
||||
return edid;
|
||||
|
||||
carp:
|
||||
if (print_bad_edid) {
|
||||
dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
|
||||
drm_get_connector_name(connector), j);
|
||||
}
|
||||
connector->bad_edid_counter++;
|
||||
|
||||
out:
|
||||
kfree(block);
|
||||
raw_edid = (struct edid *)fake_edid_info;
|
||||
edid = kmemdup(raw_edid, (1 + raw_edid->extensions) * EDID_LENGTH, GFP_KERNEL);
|
||||
if (!edid) {
|
||||
DRM_DEBUG_KMS("failed to allocate edid\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
return edid;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct rockchip_drm_display_ops extend_display_ops = {
|
||||
.type = ROCKCHIP_DISPLAY_TYPE_HDMI,
|
||||
.is_connected = extend_display_is_connected,
|
||||
.get_panel = extend_get_panel,
|
||||
.get_modelist = extend_get_modelist,
|
||||
.check_timing = extend_check_timing,
|
||||
.power_on = extend_display_power_on,
|
||||
// .get_edid = extend_get_edid,
|
||||
};
|
||||
|
||||
static void extend_dpms(struct device *subdrv_dev, int mode)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
/*
|
||||
* enable primary hardware only if suspended status.
|
||||
*
|
||||
* P.S. extend_dpms function would be called at booting time so
|
||||
* clk_enable could be called double time.
|
||||
*/
|
||||
|
||||
if (ctx->suspended)
|
||||
pm_runtime_get_sync(subdrv_dev);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
if (!ctx->suspended)
|
||||
pm_runtime_put_sync(subdrv_dev);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unspecified mode %d\n", mode);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
static void extend_apply(struct device *subdrv_dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(subdrv_dev);
|
||||
struct rockchip_drm_manager *mgr = ctx->subdrv.manager;
|
||||
struct rockchip_drm_manager_ops *mgr_ops = mgr->ops;
|
||||
struct rockchip_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
|
||||
struct extend_win_data *win_data;
|
||||
int i;
|
||||
|
||||
printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
for (i = 0; i < WINDOWS_NR; i++) {
|
||||
win_data = &ctx->win_data[i];
|
||||
if (win_data->enabled && (ovl_ops && ovl_ops->commit))
|
||||
ovl_ops->commit(subdrv_dev, i);
|
||||
}
|
||||
|
||||
if (mgr_ops && mgr_ops->commit)
|
||||
mgr_ops->commit(subdrv_dev);
|
||||
}
|
||||
|
||||
static void extend_commit(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
struct rockchip_drm_panel_info *panel = (struct rockchip_drm_panel_info *)extend_get_panel(dev);
|
||||
|
||||
// printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
drm_disp->mode = &panel->timing;
|
||||
|
||||
drm_disp->enable = true;
|
||||
rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
|
||||
}
|
||||
|
||||
static int extend_enable_vblank(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return -EPERM;
|
||||
|
||||
ctx->vblank_en = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void extend_disable_vblank(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
ctx->vblank_en = false;
|
||||
}
|
||||
|
||||
static void extend_wait_for_vblank(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
#if 1
|
||||
atomic_set(&ctx->wait_vsync_event, 1);
|
||||
|
||||
if (!wait_event_timeout(ctx->wait_vsync_queue,
|
||||
!atomic_read(&ctx->wait_vsync_event),
|
||||
DRM_HZ/20))
|
||||
DRM_DEBUG_KMS("vblank wait timed out.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void extend_event_call_back_handle(struct rk_drm_display *drm_disp,int win_id,int event)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(g_dev);
|
||||
struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
|
||||
struct rockchip_drm_manager *manager = subdrv->manager;
|
||||
struct drm_device *drm_dev = subdrv->drm_dev;
|
||||
switch(event){
|
||||
case RK_DRM_CALLBACK_VSYNC:
|
||||
/* check the crtc is detached already from encoder */
|
||||
if (manager->pipe < 0)
|
||||
return;
|
||||
|
||||
drm_handle_vblank(drm_dev, manager->pipe);
|
||||
rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
|
||||
|
||||
/* set wait vsync event to zero and wake up queue. */
|
||||
if (atomic_read(&ctx->wait_vsync_event)) {
|
||||
atomic_set(&ctx->wait_vsync_event, 0);
|
||||
DRM_WAKEUP(&ctx->wait_vsync_queue);
|
||||
}
|
||||
break;
|
||||
case RK_DRM_CALLBACK_HOTPLUG:
|
||||
#if 0
|
||||
if(0){//primary_is_display == 0){
|
||||
printk(KERN_ERR"-->%s waitfor hotplug event %d\n",__func__,event);
|
||||
int is_connected = drm_disp->is_connected;
|
||||
drm_disp->is_connected = false;
|
||||
|
||||
if (!wait_event_timeout(wait_primary_queue,
|
||||
primary_is_display,
|
||||
20*1000)){
|
||||
printk(KERN_ERR"-->%s waitfot hotplug event %d timeout\n",__func__,event);
|
||||
}
|
||||
drm_disp->is_connected = true;
|
||||
}
|
||||
#endif
|
||||
printk(KERN_ERR"-->%s hotplug event %d\n",__func__,event);
|
||||
drm_helper_hpd_irq_event(drm_dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR"-->%s unhandle event %d\n",__func__,event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void extend_get_max_resol(void *ctx, unsigned int *width,
|
||||
unsigned int *height)
|
||||
{
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
*width = MAX_HDMI_WIDTH;
|
||||
*height = MAX_HDMI_HEIGHT;
|
||||
}
|
||||
static struct rockchip_drm_manager_ops extend_manager_ops = {
|
||||
.dpms = extend_dpms,
|
||||
.apply = extend_apply,
|
||||
.commit = extend_commit,
|
||||
.enable_vblank = extend_enable_vblank,
|
||||
.disable_vblank = extend_disable_vblank,
|
||||
.wait_for_vblank = extend_wait_for_vblank,
|
||||
.get_max_resol = extend_get_max_resol,
|
||||
};
|
||||
|
||||
static void extend_win_mode_set(struct device *dev,
|
||||
struct rockchip_drm_overlay *overlay)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
struct extend_win_data *win_data;
|
||||
int win;
|
||||
unsigned long offset;
|
||||
struct list_head *pos,*head;
|
||||
struct fb_modelist *modelist;
|
||||
struct fb_videomode *mode;
|
||||
struct drm_display_mode *disp_mode = NULL;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!overlay) {
|
||||
dev_err(dev, "overlay is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
win = overlay->zpos;
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
return;
|
||||
|
||||
offset = overlay->fb_x * (overlay->bpp >> 3);
|
||||
offset += overlay->fb_y * overlay->pitch;
|
||||
|
||||
// printk("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
|
||||
// printk("crtc_x=%d crtc_y=%d crtc_width=%d crtc_height=%d\n",overlay->crtc_x,overlay->crtc_y,overlay->crtc_width,overlay->crtc_height);
|
||||
// printk("fb_width=%d fb_height=%d dma_addr=%x offset=%x\n",overlay->fb_width,overlay->fb_height,overlay->dma_addr[0],offset);
|
||||
|
||||
win_data = &ctx->win_data[win];
|
||||
|
||||
win_data->offset_x = overlay->crtc_x;
|
||||
win_data->offset_y = overlay->crtc_y;
|
||||
win_data->ovl_width = overlay->crtc_width;
|
||||
win_data->ovl_height = overlay->crtc_height;
|
||||
win_data->fb_width = overlay->fb_width;
|
||||
win_data->fb_height = overlay->fb_height;
|
||||
win_data->dma_addr = overlay->dma_addr[0] + offset;
|
||||
win_data->bpp = overlay->bpp;
|
||||
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
|
||||
(overlay->bpp >> 3);
|
||||
win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
|
||||
head = drm_disp->modelist;
|
||||
list_for_each(pos,head){
|
||||
modelist = list_entry(pos, struct fb_modelist, list);
|
||||
mode = &modelist->mode;
|
||||
if(mode->xres == overlay->mode_width && mode->yres == overlay->mode_height
|
||||
&& mode->pixclock == overlay->pixclock)
|
||||
break;
|
||||
}
|
||||
if(drm_disp->mode != mode){
|
||||
printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
drm_disp->mode = mode;
|
||||
printk("overlay [%dx%d-%d] mode[%dx%d-%d]\n",overlay->mode_width,overlay->mode_height,overlay->pixclock,mode->xres,mode->yres,mode->pixclock);
|
||||
// printk("overlay->mode_width=%d overlay->mode_height=%d mode_width=%d mode_height=%d",overlay->mode_width,overlay->mode_height,mode->xres,mode->yres);
|
||||
|
||||
drm_disp->enable = true;
|
||||
rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void extend_win_set_pixfmt(struct device *dev, unsigned int win)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct extend_win_data *win_data = &ctx->win_data[win];
|
||||
}
|
||||
|
||||
static void extend_win_set_colkey(struct device *dev, unsigned int win)
|
||||
{
|
||||
// struct extend_context *ctx = get_extend_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
}
|
||||
|
||||
ktime_t win_start;
|
||||
ktime_t win_end;
|
||||
ktime_t win_start1;
|
||||
ktime_t win_end1;
|
||||
static void extend_win_commit(struct device *dev, int zpos)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
struct rk_win_data *rk_win = NULL;
|
||||
struct extend_win_data *win_data;
|
||||
int win = zpos;
|
||||
unsigned long val, size;
|
||||
u32 xpos, ypos;
|
||||
|
||||
//printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
return;
|
||||
if(win == 0){
|
||||
win_start = ktime_get();
|
||||
win_start = ktime_sub(win_start, win_end);
|
||||
// printk("user flip buffer time %dms\n", (int)ktime_to_ms(win_start));
|
||||
// win_start = ktime_get();
|
||||
}
|
||||
rk_win = &drm_disp->win[win];
|
||||
win_data = &ctx->win_data[win];
|
||||
switch(win_data->bpp){
|
||||
case 32:
|
||||
rk_win->format = ARGB888;
|
||||
break;
|
||||
case 24:
|
||||
rk_win->format = RGB888;
|
||||
break;
|
||||
case 16:
|
||||
rk_win->format = RGB565;
|
||||
break;
|
||||
default:
|
||||
printk("not support format %d\n",win_data->bpp);
|
||||
break;
|
||||
}
|
||||
|
||||
rk_win->xpos = win_data->offset_x;
|
||||
rk_win->ypos = win_data->offset_y;
|
||||
rk_win->xact = win_data->ovl_width;
|
||||
rk_win->yact = win_data->ovl_height;
|
||||
rk_win->xsize = win_data->ovl_width;
|
||||
rk_win->ysize = win_data->ovl_height;
|
||||
rk_win->xvir = win_data->fb_width;
|
||||
rk_win->yrgb_addr = win_data->dma_addr;
|
||||
rk_win->enabled = true;
|
||||
|
||||
rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
|
||||
|
||||
win_data->enabled = true;
|
||||
if(win ==0){
|
||||
// win_end = ktime_get();
|
||||
// win_end = ktime_sub(win_end, win_start);
|
||||
// printk("flip buffer time %dus\n", (int)ktime_to_us(win_end));
|
||||
win_end = ktime_get();
|
||||
}
|
||||
}
|
||||
|
||||
static void extend_win_disable(struct device *dev, int zpos)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
struct extend_win_data *win_data;
|
||||
int win = zpos;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
return;
|
||||
|
||||
win_data = &ctx->win_data[win];
|
||||
|
||||
if (ctx->suspended) {
|
||||
/* do not resume this window*/
|
||||
win_data->resume = false;
|
||||
return;
|
||||
}
|
||||
drm_disp->win[win].enabled = false;
|
||||
rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
|
||||
|
||||
win_data->enabled = false;
|
||||
}
|
||||
|
||||
static struct rockchip_drm_overlay_ops extend_overlay_ops = {
|
||||
.mode_set = extend_win_mode_set,
|
||||
.commit = extend_win_commit,
|
||||
.disable = extend_win_disable,
|
||||
};
|
||||
|
||||
static struct rockchip_drm_manager extend_manager = {
|
||||
.pipe = -1,
|
||||
.ops = &extend_manager_ops,
|
||||
.overlay_ops = &extend_overlay_ops,
|
||||
.display_ops = &extend_display_ops,
|
||||
};
|
||||
#if 0
|
||||
static irqreturn_t extend_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct extend_context *ctx = (struct extend_context *)dev_id;
|
||||
struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
|
||||
struct drm_device *drm_dev = subdrv->drm_dev;
|
||||
struct rockchip_drm_manager *manager = subdrv->manager;
|
||||
u32 intr0_reg;
|
||||
|
||||
|
||||
|
||||
/* check the crtc is detached already from encoder */
|
||||
if (manager->pipe < 0)
|
||||
goto out;
|
||||
|
||||
drm_handle_vblank(drm_dev, manager->pipe);
|
||||
rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
|
||||
|
||||
/* set wait vsync event to zero and wake up queue. */
|
||||
if (atomic_read(&ctx->wait_vsync_event)) {
|
||||
atomic_set(&ctx->wait_vsync_event, 0);
|
||||
DRM_WAKEUP(&ctx->wait_vsync_queue);
|
||||
}
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
static int extend_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* enable drm irq mode.
|
||||
* - with irq_enabled = 1, we can use the vblank feature.
|
||||
*
|
||||
* P.S. note that we wouldn't use drm irq handler but
|
||||
* just specific driver own one instead because
|
||||
* drm framework supports only one irq handler.
|
||||
*/
|
||||
drm_dev->irq_enabled = 1;
|
||||
|
||||
/*
|
||||
* with vblank_disable_allowed = 1, vblank interrupt will be disabled
|
||||
* by drm timer once a current process gives up ownership of
|
||||
* vblank event.(after drm_vblank_put function is called)
|
||||
*/
|
||||
drm_dev->vblank_disable_allowed = 1;
|
||||
|
||||
/* attach this sub driver to iommu mapping if supported. */
|
||||
if (is_drm_iommu_supported(drm_dev))
|
||||
drm_iommu_attach_device(drm_dev, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void extend_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* detach this sub driver from iommu mapping if supported. */
|
||||
if (is_drm_iommu_supported(drm_dev))
|
||||
drm_iommu_detach_device(drm_dev, dev);
|
||||
}
|
||||
|
||||
|
||||
static void extend_clear_win(struct extend_context *ctx, int win)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void extend_window_suspend(struct device *dev)
|
||||
{
|
||||
struct extend_win_data *win_data = NULL;
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < WINDOWS_NR; i++) {
|
||||
win_data = &ctx->win_data[i];
|
||||
win_data->resume = win_data->enabled;
|
||||
extend_win_disable(dev, i);
|
||||
}
|
||||
extend_wait_for_vblank(dev);
|
||||
}
|
||||
|
||||
static void extend_window_resume(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
struct extend_win_data *win_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < WINDOWS_NR; i++) {
|
||||
win_data = &ctx->win_data[i];
|
||||
win_data->enabled = win_data->resume;
|
||||
win_data->resume = false;
|
||||
}
|
||||
}
|
||||
|
||||
static int extend_activate(struct extend_context *ctx, bool enable)
|
||||
{
|
||||
struct device *dev = ctx->subdrv.dev;
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
if (enable) {
|
||||
int ret;
|
||||
|
||||
ctx->suspended = false;
|
||||
|
||||
drm_disp->enable = true;
|
||||
|
||||
rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_BLANK);
|
||||
|
||||
/* if vblank was enabled status, enable it again. */
|
||||
if (ctx->vblank_en)
|
||||
extend_enable_vblank(dev);
|
||||
|
||||
extend_window_resume(dev);
|
||||
} else {
|
||||
extend_window_suspend(dev);
|
||||
|
||||
drm_disp->enable = false;
|
||||
|
||||
rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_BLANK);
|
||||
|
||||
ctx->suspended = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int extend_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct extend_context *ctx;
|
||||
struct rockchip_drm_subdrv *subdrv;
|
||||
struct rockchip_drm_panel_info *panel;
|
||||
struct rk_drm_display *drm_display = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
g_dev = dev;
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
panel = devm_kzalloc(dev, sizeof(struct rockchip_drm_panel_info), GFP_KERNEL);
|
||||
ctx->panel = panel;
|
||||
|
||||
drm_display = rk_drm_get_diplay(RK_DRM_EXTEND_SCREEN);
|
||||
ctx->drm_disp = drm_display;
|
||||
ctx->default_win = 0;
|
||||
|
||||
drm_display->event_call_back = extend_event_call_back_handle;
|
||||
|
||||
DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
|
||||
atomic_set(&ctx->wait_vsync_event, 0);
|
||||
|
||||
subdrv = &ctx->subdrv;
|
||||
|
||||
subdrv->dev = dev;
|
||||
subdrv->manager = &extend_manager;
|
||||
subdrv->probe = extend_subdrv_probe;
|
||||
subdrv->remove = extend_subdrv_remove;
|
||||
|
||||
mutex_init(&ctx->lock);
|
||||
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
//extend_commit(dev);
|
||||
extend_activate(ctx, true);
|
||||
|
||||
rockchip_drm_subdrv_register(subdrv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int extend_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct extend_context *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
rockchip_drm_subdrv_unregister(&ctx->subdrv);
|
||||
|
||||
if (ctx->suspended)
|
||||
goto out;
|
||||
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
out:
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int extend_suspend(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
|
||||
/*
|
||||
* do not use pm_runtime_suspend(). if pm_runtime_suspend() is
|
||||
* called here, an error would be returned by that interface
|
||||
* because the usage_count of pm runtime is more than 1.
|
||||
*/
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return extend_activate(ctx, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int extend_resume(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
|
||||
/*
|
||||
* if entered to sleep when lcd panel was on, the usage_count
|
||||
* of pm runtime would still be 1 so in this case, fimd driver
|
||||
* should be on directly not drawing on pm runtime interface.
|
||||
*/
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
int ret;
|
||||
|
||||
ret = extend_activate(ctx, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* in case of dpms on(standby), extend_apply function will
|
||||
* be called by encoder's dpms callback to update fimd's
|
||||
* registers but in case of sleep wakeup, it's not.
|
||||
* so extend_apply function should be called at here.
|
||||
*/
|
||||
extend_apply(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int extend_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return extend_activate(ctx, false);
|
||||
}
|
||||
|
||||
static int extend_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct extend_context *ctx = get_extend_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return extend_activate(ctx, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops extend_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(extend_suspend, extend_resume)
|
||||
SET_RUNTIME_PM_OPS(extend_runtime_suspend, extend_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
struct platform_driver extend_platform_driver = {
|
||||
.probe = extend_probe,
|
||||
.remove = extend_remove,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "extend-display",
|
||||
.pm = &extend_pm_ops,
|
||||
},
|
||||
};
|
||||
37
drivers/gpu/drm/rockchip/rockchip_drm_extend.h
Normal file
37
drivers/gpu/drm/rockchip/rockchip_drm_extend.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "../../../video/rockchip/rk_drm_fb.h"
|
||||
#include "../../../video/rockchip/hdmi/rk_hdmi.h"
|
||||
#define WINDOWS_NR 4
|
||||
#define MAX_HDMI_WIDTH 1920
|
||||
#define MAX_HDMI_HEIGHT 1080
|
||||
|
||||
#define get_extend_context(dev) platform_get_drvdata(to_platform_device(dev))
|
||||
|
||||
struct extend_win_data {
|
||||
unsigned int offset_x;
|
||||
unsigned int offset_y;
|
||||
unsigned int ovl_width;
|
||||
unsigned int ovl_height;
|
||||
unsigned int fb_width;
|
||||
unsigned int fb_height;
|
||||
unsigned int bpp;
|
||||
dma_addr_t dma_addr;
|
||||
unsigned int buf_offsize;
|
||||
unsigned int line_size; /* bytes */
|
||||
bool enabled;
|
||||
bool resume;
|
||||
};
|
||||
|
||||
struct extend_context {
|
||||
struct rockchip_drm_subdrv subdrv;
|
||||
int vblank_en;
|
||||
struct drm_crtc *crtc;
|
||||
struct rk_drm_display *drm_disp;
|
||||
struct extend_win_data win_data[WINDOWS_NR];
|
||||
unsigned int default_win;
|
||||
bool suspended;
|
||||
struct mutex lock;
|
||||
wait_queue_head_t wait_vsync_queue;
|
||||
atomic_t wait_vsync_event;
|
||||
|
||||
struct rockchip_drm_panel_info *panel;
|
||||
};
|
||||
@@ -136,8 +136,10 @@ int rockchip_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
overlay->mode_width = crtc->mode.hdisplay;
|
||||
overlay->mode_height = crtc->mode.vdisplay;
|
||||
overlay->refresh = crtc->mode.vrefresh;
|
||||
overlay->pixclock = crtc->mode.clock*1000;
|
||||
overlay->scan_flag = crtc->mode.flags;
|
||||
|
||||
// printk("--->yzq %s crtc->mode->refresh =%d \n",__func__,crtc->mode.vrefresh);
|
||||
DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
|
||||
overlay->crtc_x, overlay->crtc_y,
|
||||
overlay->crtc_width, overlay->crtc_height);
|
||||
|
||||
@@ -39,11 +39,10 @@ static struct device *g_dev = NULL;
|
||||
|
||||
static bool primary_display_is_connected(struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO. */
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void *primary_get_panel(struct device *dev)
|
||||
@@ -140,12 +139,13 @@ static void primary_commit(struct device *dev)
|
||||
{
|
||||
struct primary_context *ctx = get_primary_context(dev);
|
||||
struct rk_drm_display *drm_disp = ctx->drm_disp;
|
||||
struct rockchip_drm_panel_info *panel = (struct rockchip_drm_panel_info *)primary_get_panel(dev);
|
||||
struct fb_videomode *mode;
|
||||
|
||||
printk(KERN_ERR"%s %d\n", __func__,__LINE__);
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
drm_disp->mode_id = drm_disp->best_mode;
|
||||
drm_disp->mode = &panel->timing;
|
||||
drm_disp->enable = true;
|
||||
rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
|
||||
}
|
||||
@@ -201,7 +201,6 @@ static void primary_event_call_back_handle(struct rk_drm_display *drm_disp,int w
|
||||
|
||||
drm_handle_vblank(drm_dev, manager->pipe);
|
||||
rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
|
||||
|
||||
/* set wait vsync event to zero and wake up queue. */
|
||||
if (atomic_read(&ctx->wait_vsync_event)) {
|
||||
atomic_set(&ctx->wait_vsync_event, 0);
|
||||
@@ -280,7 +279,12 @@ static void primary_win_set_colkey(struct device *dev, unsigned int win)
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
static ktime_t win_start;
|
||||
static ktime_t win_end;
|
||||
static ktime_t win_start1;
|
||||
static ktime_t win_end1;
|
||||
#endif
|
||||
static void primary_win_commit(struct device *dev, int zpos)
|
||||
{
|
||||
struct primary_context *ctx = get_primary_context(dev);
|
||||
@@ -301,6 +305,14 @@ static void primary_win_commit(struct device *dev, int zpos)
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
return;
|
||||
#if 0
|
||||
if(win == 0){
|
||||
win_start = ktime_get();
|
||||
win_start = ktime_sub(win_start, win_end);
|
||||
printk("user flip buffer time %dus\n", (int)ktime_to_us(win_start));
|
||||
// win_start = ktime_get();
|
||||
}
|
||||
#endif
|
||||
rk_win = &drm_disp->win[win];
|
||||
win_data = &ctx->win_data[win];
|
||||
switch(win_data->bpp){
|
||||
@@ -331,6 +343,14 @@ static void primary_win_commit(struct device *dev, int zpos)
|
||||
rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
|
||||
|
||||
win_data->enabled = true;
|
||||
#if 0
|
||||
if(win ==0){
|
||||
// win_end = ktime_get();
|
||||
// win_end = ktime_sub(win_end, win_start);
|
||||
// printk("flip buffer time %dus\n", (int)ktime_to_us(win_end));
|
||||
win_end = ktime_get();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -513,7 +533,8 @@ static int primary_probe(struct platform_device *pdev)
|
||||
struct rockchip_drm_subdrv *subdrv;
|
||||
struct rockchip_drm_panel_info *panel;
|
||||
struct rk_drm_display *drm_display = NULL;
|
||||
int ret = -EINVAL;
|
||||
struct fb_modelist *modelist;
|
||||
struct fb_videomode *mode;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
@@ -528,7 +549,9 @@ static int primary_probe(struct platform_device *pdev)
|
||||
drm_display = rk_drm_get_diplay(RK_DRM_PRIMARY_SCREEN);
|
||||
ctx->drm_disp = drm_display;
|
||||
ctx->default_win = 0;
|
||||
memcpy(&panel->timing,drm_display->mode,sizeof(struct fb_videomode));
|
||||
modelist = list_first_entry(drm_display->modelist, struct fb_modelist, list);
|
||||
mode = &modelist->mode;
|
||||
memcpy(&panel->timing,mode,sizeof(struct fb_videomode));
|
||||
|
||||
drm_display->event_call_back = primary_event_call_back_handle;
|
||||
|
||||
@@ -549,7 +572,7 @@ static int primary_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
primary_commit(dev);
|
||||
//primary_commit(dev);
|
||||
primary_activate(ctx, true);
|
||||
|
||||
rockchip_drm_subdrv_register(subdrv);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
menuconfig RK_HDMI
|
||||
bool "Rockchip HDMI support"
|
||||
depends on FB_ROCKCHIP
|
||||
depends on FB_ROCKCHIP || DRM_ROCKCHIP
|
||||
select FB_MODE_HELPERS
|
||||
|
||||
if RK_HDMI
|
||||
|
||||
@@ -171,10 +171,16 @@ static struct rk_display_driver display_hdmi = {
|
||||
};
|
||||
|
||||
static struct rk_display_device *display_device_hdmi = NULL;
|
||||
#ifdef CONFIG_DRM_ROCKCHIP
|
||||
extern void rk_drm_display_register(struct rk_display_ops *extend_ops, void *displaydata,int type);
|
||||
#endif
|
||||
|
||||
void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent)
|
||||
{
|
||||
display_device_hdmi = rk_display_device_register(&display_hdmi, parent, hdmi);
|
||||
#ifdef CONFIG_DRM_ROCKCHIP
|
||||
rk_drm_display_register(&hdmi_display_ops,hdmi,SCREEN_HDMI);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
|
||||
|
||||
@@ -3144,6 +3144,9 @@ static irqreturn_t rk3288_lcdc_isr(int irq, void *dev_id)
|
||||
complete(&(lcdc_dev->driver.frame_done));
|
||||
spin_unlock(&(lcdc_dev->driver.cpl_lock));
|
||||
}
|
||||
#ifdef CONFIG_DRM_ROCKCHIP
|
||||
lcdc_dev->driver.irq_call_back(&lcdc_dev->driver);
|
||||
#endif
|
||||
lcdc_dev->driver.vsync_info.timestamp = timestamp;
|
||||
wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/rk_fb.h>
|
||||
#include <linux/linux_logo.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <drm/drm_os_linux.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#ifdef CONFIG_OF
|
||||
#include <linux/of.h>
|
||||
@@ -38,6 +39,7 @@
|
||||
#include <dt-bindings/rkfb/rk_fb.h>
|
||||
#endif
|
||||
|
||||
#include <linux/display-sys.h>
|
||||
#include "rk_drm_fb.h"
|
||||
__weak int support_uboot_display(void)
|
||||
{
|
||||
@@ -47,6 +49,21 @@ static struct platform_device *drm_fb_pdev;
|
||||
static struct rk_fb_trsm_ops *trsm_lvds_ops;
|
||||
static struct rk_fb_trsm_ops *trsm_edp_ops;
|
||||
static struct rk_fb_trsm_ops *trsm_mipi_ops;
|
||||
static struct rk_display_device *disp_hdmi_devices;
|
||||
void rk_drm_display_register(struct rk_display_ops *extend_ops, void *displaydata,int type)
|
||||
{
|
||||
switch(type) {
|
||||
case SCREEN_HDMI:
|
||||
disp_hdmi_devices = kzalloc(sizeof(struct rk_display_device), GFP_KERNEL);
|
||||
disp_hdmi_devices->priv_data = displaydata;
|
||||
disp_hdmi_devices->ops = extend_ops;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s:un supported extend display:%d!\n",
|
||||
__func__, type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
|
||||
{
|
||||
switch (type) {
|
||||
@@ -70,6 +87,30 @@ int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rk_display_device *rk_drm_extend_display_get(int type)
|
||||
{
|
||||
struct rk_display_device *extend_display = NULL;
|
||||
switch (type) {
|
||||
case SCREEN_HDMI:
|
||||
if(disp_hdmi_devices)
|
||||
extend_display = disp_hdmi_devices;
|
||||
else
|
||||
printk(KERN_WARNING "%s:screen hdmi ops is NULL!\n",__func__);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s:un supported extend display:%d!\n",
|
||||
__func__, type);
|
||||
break;
|
||||
}
|
||||
return extend_display;
|
||||
}
|
||||
#if 0
|
||||
struct void *get_extend_drv(void)
|
||||
{
|
||||
struct rk_display_device *extend_display = rk_drm_extend_display_get(SCREEN_HDMI);
|
||||
return extend_display->priv_data;
|
||||
}
|
||||
#endif
|
||||
struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type)
|
||||
{
|
||||
struct rk_fb_trsm_ops *ops;
|
||||
@@ -320,8 +361,8 @@ static int init_lcdc_device_driver(struct rk_drm_screen_private *screen_priv,
|
||||
if (dev_drv->prop == PRMRY) {
|
||||
rk_fb_set_prmry_screen(screen);
|
||||
rk_fb_get_prmry_screen(screen);
|
||||
dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
|
||||
}
|
||||
dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -483,19 +524,45 @@ static int rk_fb_wait_for_vsync_thread(void *data)
|
||||
int ret = wait_event_interruptible(dev_drv->vsync_info.wait,
|
||||
!ktime_equal(timestamp, dev_drv->vsync_info.timestamp) &&
|
||||
(dev_drv->vsync_info.active || dev_drv->vsync_info.irq_stop));
|
||||
|
||||
#if 1
|
||||
if(atomic_read(&drm_screen_priv->wait_vsync_done)){
|
||||
atomic_set(&drm_screen_priv->wait_vsync_done,0);
|
||||
DRM_WAKEUP(&drm_screen_priv->wait_vsync_queue);
|
||||
}
|
||||
if(!ret && drm_display->event_call_back)
|
||||
drm_display->event_call_back(drm_display,0,RK_DRM_CALLBACK_VSYNC);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rk_drm_irq_handle(struct rk_lcdc_driver *dev_drv)
|
||||
{
|
||||
struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
|
||||
struct rk_drm_screen_private *drm_screen_priv = NULL;
|
||||
struct rk_drm_display *drm_display = NULL;
|
||||
if(dev_drv->prop == PRMRY)
|
||||
drm_screen_priv = &rk_drm_priv->screen_priv[0];
|
||||
else if(dev_drv->prop == EXTEND)
|
||||
drm_screen_priv = &rk_drm_priv->screen_priv[1];
|
||||
if(drm_screen_priv == NULL)
|
||||
return -1;
|
||||
drm_display = &drm_screen_priv->drm_disp;
|
||||
if(atomic_read(&drm_screen_priv->wait_vsync_done)){
|
||||
atomic_set(&drm_screen_priv->wait_vsync_done,0);
|
||||
DRM_WAKEUP(&drm_screen_priv->wait_vsync_queue);
|
||||
}
|
||||
|
||||
if(drm_display->event_call_back)
|
||||
drm_display->event_call_back(drm_display,0,RK_DRM_CALLBACK_VSYNC);
|
||||
}
|
||||
int rk_fb_register(struct rk_lcdc_driver *dev_drv,
|
||||
struct rk_lcdc_win *win, int id)
|
||||
{
|
||||
struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
|
||||
struct rk_drm_display *drm_display = NULL;
|
||||
struct rk_win_data *win_data = NULL;
|
||||
struct rk_drm_screen_private *drm_screen_priv = NULL;
|
||||
int i=0;
|
||||
|
||||
if (rk_drm_priv->num_screen == RK30_MAX_LCDC_SUPPORT)
|
||||
@@ -504,29 +571,53 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
|
||||
if (!rk_drm_priv->screen_priv[i].lcdc_dev_drv)
|
||||
break;
|
||||
}
|
||||
|
||||
rk_drm_priv->num_screen++;
|
||||
rk_drm_priv->screen_priv[i].lcdc_dev_drv = dev_drv;
|
||||
rk_drm_priv->screen_priv[i].lcdc_dev_drv->id = id;
|
||||
drm_screen_priv = &rk_drm_priv->screen_priv[i];
|
||||
drm_screen_priv->lcdc_dev_drv = dev_drv;
|
||||
drm_screen_priv->lcdc_dev_drv->id = id;
|
||||
|
||||
init_lcdc_device_driver(&rk_drm_priv->screen_priv[i],win,i);
|
||||
init_lcdc_device_driver(drm_screen_priv,win,i);
|
||||
dev_drv->irq_call_back = rk_drm_irq_handle;
|
||||
|
||||
drm_display = &rk_drm_priv->screen_priv[i].drm_disp;
|
||||
drm_display = &drm_screen_priv->drm_disp;
|
||||
drm_display->num_win = dev_drv->lcdc_win_num;
|
||||
atomic_set(&drm_screen_priv->wait_vsync_done, 1);
|
||||
DRM_INIT_WAITQUEUE(&drm_screen_priv->wait_vsync_queue);
|
||||
if(dev_drv->prop == PRMRY){
|
||||
struct fb_modelist *modelist_new;
|
||||
struct fb_modelist *modelist;
|
||||
struct fb_videomode *mode;
|
||||
drm_display->modelist = kmalloc(sizeof(struct list_head),GFP_KERNEL);
|
||||
INIT_LIST_HEAD(drm_display->modelist);
|
||||
modelist_new = kmalloc(sizeof(struct fb_modelist),
|
||||
GFP_KERNEL);
|
||||
drm_display->screen_type = RK_DRM_PRIMARY_SCREEN;
|
||||
drm_display->num_videomode = 1;
|
||||
drm_display->best_mode = 0;
|
||||
drm_display->is_connected = 1;
|
||||
drm_display->mode = &dev_drv->cur_screen->mode;
|
||||
printk("----->yzq mode dclk=%d\n",drm_display->mode->pixclock);
|
||||
memcpy(&modelist_new->mode,&dev_drv->cur_screen->mode,sizeof(struct fb_videomode));
|
||||
|
||||
// printk("---->yzq mode xres=%d yres=%d \n",modelist_new->mode.xres,modelist_new->mode.yres);
|
||||
list_add_tail(&modelist_new->list,drm_display->modelist);
|
||||
|
||||
modelist = list_first_entry(drm_display->modelist, struct fb_modelist, list);
|
||||
mode=&modelist->mode;
|
||||
// printk("---->yzq 1mode xres=%d yres=%d \n",mode->xres,mode->yres);
|
||||
|
||||
}else if(dev_drv->prop == EXTEND){
|
||||
struct list_head *modelist;
|
||||
drm_screen_priv->ex_display = rk_drm_extend_display_get(SCREEN_HDMI);
|
||||
// printk("------>yzq ex_display=%x\n",drm_screen_priv->ex_display);
|
||||
drm_display->screen_type = RK_DRM_EXTEND_SCREEN;
|
||||
drm_display->num_videomode = 1;
|
||||
drm_display->best_mode = 0;
|
||||
drm_display->is_connected = 0;
|
||||
#if 0
|
||||
drm_screen_priv->ex_display->ops->getmodelist(drm_screen_priv->ex_display,&modelist);
|
||||
|
||||
memcpy(&drm_display->modelist,modelist,sizeof(struct list_head));
|
||||
drm_display->is_connected = drm_screen_priv->ex_display->ops->getstatus(drm_screen_priv->ex_display);
|
||||
#endif
|
||||
}
|
||||
if (dev_drv->prop == PRMRY) {
|
||||
if (1){//dev_drv->prop == PRMRY) {
|
||||
init_waitqueue_head(&dev_drv->vsync_info.wait);
|
||||
dev_drv->vsync_info.thread = kthread_run(rk_fb_wait_for_vsync_thread,
|
||||
dev_drv, "fb-vsync");
|
||||
@@ -593,6 +684,80 @@ static int rk_drm_screen_blank(struct rk_drm_display *drm_disp)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/**********************************************************************
|
||||
this is for hdmi
|
||||
name: lcdc device name ,lcdc0 , lcdc1
|
||||
***********************************************************************/
|
||||
struct rk_lcdc_driver *rk_get_lcdc_drv(char *name)
|
||||
{
|
||||
struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
|
||||
int i = 0;
|
||||
for (i = 0; i < rk_drm_priv->num_screen; i++) {
|
||||
if (!strcmp(rk_drm_priv->screen_priv[i].lcdc_dev_drv->name, name))
|
||||
break;
|
||||
}
|
||||
return rk_drm_priv->screen_priv[i].lcdc_dev_drv;
|
||||
|
||||
}
|
||||
int rk_fb_switch_screen(struct rk_screen *screen , int enable, int lcdc_id)
|
||||
{
|
||||
struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
|
||||
struct rk_lcdc_driver *dev_drv = NULL;
|
||||
struct rk_drm_display *drm_disp = NULL;
|
||||
char name[6];
|
||||
int i;
|
||||
|
||||
sprintf(name, "lcdc%d", lcdc_id);
|
||||
|
||||
if (rk_drm_priv->disp_mode != DUAL) {
|
||||
dev_drv = rk_drm_priv->screen_priv[0].lcdc_dev_drv;
|
||||
} else {
|
||||
|
||||
for (i = 0; i < rk_drm_priv->num_screen; i++) {
|
||||
if (rk_drm_priv->screen_priv[i].lcdc_dev_drv->prop == EXTEND) {
|
||||
drm_disp = &rk_drm_priv->screen_priv[i].drm_disp;
|
||||
dev_drv = rk_drm_priv->screen_priv[i].lcdc_dev_drv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == rk_drm_priv->num_screen) {
|
||||
printk(KERN_ERR "%s driver not found!", name);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
printk("hdmi %s lcdc%d\n", enable ? "connect to" : "remove from", dev_drv->id);
|
||||
|
||||
|
||||
if(enable && !drm_disp->is_connected ){
|
||||
struct list_head *modelist;
|
||||
struct fb_modelist *modelist1;
|
||||
struct fb_videomode *mode;
|
||||
struct rk_display_device *ex_display = rk_drm_priv->screen_priv[i].ex_display;
|
||||
memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
|
||||
if(ex_display == NULL)
|
||||
ex_display = rk_drm_extend_display_get(SCREEN_HDMI);
|
||||
rk_drm_priv->screen_priv[i].ex_display = ex_display;
|
||||
ex_display->ops->getmodelist(ex_display,&modelist);
|
||||
|
||||
drm_disp->modelist = modelist;
|
||||
|
||||
drm_disp->is_connected = true;
|
||||
drm_disp->event_call_back(drm_disp,0,RK_DRM_CALLBACK_HOTPLUG);
|
||||
}else{
|
||||
// printk("----->yzq %s %d \n",__func__,__LINE__);
|
||||
drm_disp->is_connected = false;
|
||||
drm_disp->event_call_back(drm_disp,0,RK_DRM_CALLBACK_HOTPLUG);
|
||||
// printk("----->yzq %s %d \n",__func__,__LINE__);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
static int rk_drm_screen_videomode_set(struct rk_drm_display *drm_disp)
|
||||
{
|
||||
// struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
|
||||
@@ -605,14 +770,29 @@ static int rk_drm_screen_videomode_set(struct rk_drm_display *drm_disp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(mode != &lcdc_dev->cur_screen->mode)
|
||||
memcpy(&lcdc_dev->cur_screen->mode,mode,sizeof(struct fb_videomode));
|
||||
|
||||
// printk("----->yzq %s %d xres=%d yres=%d refresh=%d \n",__func__,__LINE__,mode->xres,mode->yres,mode->refresh);
|
||||
if(lcdc_dev->prop == PRMRY){
|
||||
if(mode != &lcdc_dev->cur_screen->mode)
|
||||
memcpy(&lcdc_dev->cur_screen->mode,mode,sizeof(struct fb_videomode));
|
||||
|
||||
}else{
|
||||
struct rk_display_device *ex_display = drm_screen_priv->ex_display;
|
||||
if(ex_display == NULL)
|
||||
ex_display = rk_drm_extend_display_get(SCREEN_HDMI);
|
||||
|
||||
// printk("------>yzq ex_display=%x\n",ex_display);
|
||||
if(ex_display == NULL){
|
||||
printk(KERN_ERR"-->%s can not find extend display ops\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
ex_display->ops->setmode(ex_display, mode);
|
||||
}
|
||||
if(!lcdc_dev->atv_layer_cnt)
|
||||
lcdc_dev->ops->open(lcdc_dev, 0,true);
|
||||
|
||||
|
||||
lcdc_dev->ops->ovl_mgr(lcdc_dev, 3210, 1);
|
||||
lcdc_dev->ops->load_screen(lcdc_dev,1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -664,9 +844,12 @@ static int rk_drm_display_commit(struct rk_drm_display *drm_disp)
|
||||
lcdc_dev->ops->lcdc_reg_update(lcdc_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rk_drm_disp_handle(struct rk_drm_display *drm_disp,unsigned int win_id,unsigned int cmd_id)
|
||||
{
|
||||
// struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
|
||||
struct rk_drm_screen_private *drm_screen_priv =
|
||||
container_of(drm_disp, struct rk_drm_screen_private, drm_disp);
|
||||
int i=0;
|
||||
for( i=1; i<RK_DRM_CMD_MASK; i=i<<1){
|
||||
switch(i&cmd_id){
|
||||
@@ -680,8 +863,17 @@ int rk_drm_disp_handle(struct rk_drm_display *drm_disp,unsigned int win_id,unsig
|
||||
rk_drm_win_commit(drm_disp, win_id);
|
||||
break;
|
||||
case RK_DRM_DISPLAY_COMMIT:
|
||||
if(win_id & i){
|
||||
if (!wait_event_timeout(drm_screen_priv->wait_vsync_queue,
|
||||
!atomic_read(&drm_screen_priv->wait_vsync_done),
|
||||
DRM_HZ/20))
|
||||
printk("wait frame timed out.\n");
|
||||
}
|
||||
|
||||
rk_drm_display_commit(drm_disp);
|
||||
break;
|
||||
if(win_id & i){
|
||||
atomic_set(&drm_screen_priv->wait_vsync_done,1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
#define RK_DRM_WIN_MASK 0x7fff
|
||||
#define RK_DRM_CMD_MASK 0x7fff
|
||||
|
||||
#define RK_DRM_CALLBACK_VSYNC 0x1
|
||||
#define RK_DRM_CALLBACK_VSYNC 0x1
|
||||
#define RK_DRM_CALLBACK_HOTPLUG 0x2
|
||||
|
||||
#define RK_DRM_SCREEN_SET 1<<0
|
||||
#define RK_DRM_SCREEN_BLANK 1<<1
|
||||
@@ -35,13 +36,14 @@ struct rk_win_data {
|
||||
struct rk_drm_display {
|
||||
/***** hardware define *****/
|
||||
enum drm_screen_type screen_type;
|
||||
struct fb_videomode *mode;
|
||||
|
||||
struct list_head *modelist;
|
||||
int num_videomode;
|
||||
int best_mode;
|
||||
bool is_connected;
|
||||
|
||||
/***** user fill info *****/
|
||||
int mode_id;
|
||||
struct fb_videomode *mode;
|
||||
bool enable;
|
||||
struct rk_win_data win[RK30_MAX_LAYER_SUPPORT];
|
||||
int num_win;
|
||||
@@ -52,8 +54,12 @@ struct rk_drm_display {
|
||||
struct rk_drm_screen_private {
|
||||
struct rk_drm_display drm_disp;
|
||||
struct rk_screen screen;
|
||||
atomic_t wait_vsync_done;
|
||||
wait_queue_head_t wait_vsync_queue;
|
||||
struct rk_fb_trsm_ops *trsm_ops;
|
||||
struct rk_lcdc_driver *lcdc_dev_drv;
|
||||
|
||||
struct rk_display_device *ex_display;
|
||||
};
|
||||
struct rk_drm_private {
|
||||
struct rk_drm_screen_private screen_priv[RK_DRM_MAX_SCREEN_NUM];
|
||||
|
||||
@@ -515,6 +515,9 @@ struct rk_lcdc_driver {
|
||||
struct list_head pwrlist_head;
|
||||
struct rk_lcdc_drv_ops *ops;
|
||||
struct rk_fb_trsm_ops *trsm_ops;
|
||||
#ifdef CONFIG_DRM_ROCKCHIP
|
||||
void (*irq_call_back)(struct rk_lcdc_driver *driver);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user