From 1bfafc53d51f28a56acf53e7016faf8df58b4557 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Tue, 4 Oct 2016 17:29:20 +0200 Subject: [PATCH 001/104] dt-bindings: display: Add Sharp LQ150X1LG11 panel binding The Sharp 15" LQ150X1LG11 panel is an XGA TFT LCD panel. Signed-off-by: Peter Rosin Acked-by: Rob Herring Signed-off-by: Thierry Reding --- .../display/panel/sharp,lq150x1lg11.txt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt diff --git a/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt b/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt new file mode 100644 index 000000000000..0f57c3143506 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt @@ -0,0 +1,36 @@ +Sharp 15" LQ150X1LG11 XGA TFT LCD panel + +Required properties: +- compatible: should be "sharp,lq150x1lg11" +- power-supply: regulator to provide the VCC supply voltage (3.3 volts) + +Optional properties: +- backlight: phandle of the backlight device +- rlud-gpios: a single GPIO for the RL/UD (rotate 180 degrees) pin. +- sellvds-gpios: a single GPIO for the SELLVDS pin. + +If rlud-gpios and/or sellvds-gpios are not specified, the RL/UD and/or SELLVDS +pins are assumed to be handled appropriately by the hardware. + +Example: + + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 100000>; /* VBR */ + + brightness-levels = <0 20 40 60 80 100>; + default-brightness-level = <2>; + + power-supply = <&vdd_12v_reg>; /* VDD */ + enable-gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; /* XSTABY */ + }; + + panel { + compatible = "sharp,lq150x1lg11"; + + power-supply = <&vcc_3v3_reg>; /* VCC */ + + backlight = <&backlight>; + rlud-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; /* RL/UD */ + sellvds-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; /* SELLVDS */ + }; From 0f9cdd743f7f8d470fff51b11250f02fc554cf1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Lindstr=C3=B6m?= Date: Tue, 4 Oct 2016 17:29:21 +0200 Subject: [PATCH 002/104] drm/panel: simple: Add support for Sharp LQ150X1LG11 panels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Sharp 15" LQ150X1LG11 panel is an XGA TFT LCD panel. The simple-panel driver is used to get support for essential functionality of the panel. Signed-off-by: Gustaf Lindström Signed-off-by: Peter Rosin [treding@nvidia.com: change .bpc from 8 to 6] Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 113db3c4a633..76f0ef7e5b7c 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1420,6 +1420,30 @@ static const struct panel_desc sharp_lq123p1jx31 = { }, }; +static const struct drm_display_mode sharp_lq150x1lg11_mode = { + .clock = 71100, + .hdisplay = 1024, + .hsync_start = 1024 + 168, + .hsync_end = 1024 + 168 + 64, + .htotal = 1024 + 168 + 64 + 88, + .vdisplay = 768, + .vsync_start = 768 + 37, + .vsync_end = 768 + 37 + 2, + .vtotal = 768 + 37 + 2 + 8, + .vrefresh = 60, +}; + +static const struct panel_desc sharp_lq150x1lg11 = { + .modes = &sharp_lq150x1lg11_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 304, + .height = 228, + }, + .bus_format = MEDIA_BUS_FMT_RGB565_1X16, +}; + static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = { .clock = 33300, .hdisplay = 800, @@ -1682,6 +1706,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "sharp,lq123p1jx31", .data = &sharp_lq123p1jx31, + }, { + .compatible = "sharp,lq150x1lg11", + .data = &sharp_lq150x1lg11, }, { .compatible = "shelly,sca07010-bfn-lnn", .data = &shelly_sca07010_bfn_lnn, From 7ee933a1d5c47521c2b2842e5d6d29e643fd2e4a Mon Sep 17 00:00:00 2001 From: Haixia Shi Date: Tue, 11 Oct 2016 14:59:16 -0700 Subject: [PATCH 003/104] drm/panel: simple: Add support for AUO T215HVN01 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AUO T215HVN01 is a 21.5" FHD (1920x1080) color TFT LCD panel. This panel is used on the Acer Chromebase 21.5-inch All-in-One (DC221HQ). Link to spec: http://www.udmgroup.com/ftp/T215HVN01.0.pdf v2: fix alphabetical order v3: remove minor revision suffix ".0" and add link to spec v4: add dt-binding documentation Signed-off-by: Haixia Shi Tested-by: Haixia Shi Reviewed-by: Stéphane Marchesin Cc: Emil Velikov Cc: Thierry Reding Cc: David Airlie Cc: Rob Herring Cc: Mark Rutland Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Acked-by: Rob Herring Signed-off-by: Thierry Reding --- .../bindings/display/panel/auo,t215hvn01.txt | 7 +++++ drivers/gpu/drm/panel/panel-simple.c | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt diff --git a/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt b/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt new file mode 100644 index 000000000000..cbd9da3f03b1 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt @@ -0,0 +1,7 @@ +AU Optronics Corporation 21.5" FHD (1920x1080) color TFT LCD panel + +Required properties: +- compatible: should be "auo,t215hvn01" + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 76f0ef7e5b7c..140a0bc01395 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -555,6 +555,33 @@ static const struct panel_desc auo_b133htn01 = { }, }; +static const struct drm_display_mode auo_t215hvn01_mode = { + .clock = 148800, + .hdisplay = 1920, + .hsync_start = 1920 + 88, + .hsync_end = 1920 + 88 + 44, + .htotal = 1920 + 88 + 44 + 148, + .vdisplay = 1080, + .vsync_start = 1080 + 4, + .vsync_end = 1080 + 4 + 5, + .vtotal = 1080 + 4 + 5 + 36, + .vrefresh = 60, +}; + +static const struct panel_desc auo_t215hvn01 = { + .modes = &auo_t215hvn01_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 430, + .height = 270, + }, + .delay = { + .disable = 5, + .unprepare = 1000, + } +}; + static const struct drm_display_mode avic_tm070ddh03_mode = { .clock = 51200, .hdisplay = 1024, @@ -1598,6 +1625,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "auo,b133xtn01", .data = &auo_b133xtn01, + }, { + .compatible = "auo,t215hvn01", + .data = &auo_t215hvn01, }, { .compatible = "avic,tm070ddh03", .data = &avic_tm070ddh03, From 05ec0e4501f7f05ef610070294fcc806ccbbb981 Mon Sep 17 00:00:00 2001 From: Fabien Lahoudere Date: Mon, 17 Oct 2016 11:38:01 +0200 Subject: [PATCH 004/104] drm/panel: simple: Add NVD9128 as a simple panel Add New Vision Display 7.0" 800 RGB x 480 TFT LCD panel Signed-off-by: Fabien Lahoudere Acked-by: Rob Herring Signed-off-by: Thierry Reding --- .../bindings/display/panel/nvd,9128.txt | 7 +++++ .../devicetree/bindings/vendor-prefixes.txt | 1 + drivers/gpu/drm/panel/panel-simple.c | 26 +++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/nvd,9128.txt diff --git a/Documentation/devicetree/bindings/display/panel/nvd,9128.txt b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt new file mode 100644 index 000000000000..17bcd017c678 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt @@ -0,0 +1,7 @@ +New Vision Display 7.0" 800 RGB x 480 TFT LCD panel + +Required properties: +- compatible: should be "nvd,9128" + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index f0a48ea78659..d9c51d7f4aac 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -187,6 +187,7 @@ netgear NETGEAR netlogic Broadcom Corporation (formerly NetLogic Microsystems) netxeon Shenzhen Netxeon Technology CO., LTD newhaven Newhaven Display International +nvd New Vision Display nintendo Nintendo nokia Nokia nuvoton Nuvoton Technology Corporation diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 140a0bc01395..659c75941b45 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1191,6 +1191,29 @@ static const struct panel_desc nec_nl4827hc19_05b = { .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE, }; +static const struct drm_display_mode nvd_9128_mode = { + .clock = 29500, + .hdisplay = 800, + .hsync_start = 800 + 130, + .hsync_end = 800 + 130 + 98, + .htotal = 800 + 0 + 130 + 98, + .vdisplay = 480, + .vsync_start = 480 + 10, + .vsync_end = 480 + 10 + 50, + .vtotal = 480 + 0 + 10 + 50, +}; + +static const struct panel_desc nvd_9128 = { + .modes = &nvd_9128_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 156, + .height = 88, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, +}; + static const struct display_timing okaya_rs800480t_7x0gp_timing = { .pixelclock = { 30000000, 30000000, 40000000 }, .hactive = { 800, 800, 800 }, @@ -1706,6 +1729,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "nec,nl4827hc19-05b", .data = &nec_nl4827hc19_05b, + }, { + .compatible = "nvd,9128", + .data = &nvd_9128, }, { .compatible = "okaya,rs800480t-7x0gp", .data = &okaya_rs800480t_7x0gp, From 9376cad2073d2c122864754ea5f80025c8507b0b Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Fri, 28 Oct 2016 11:09:45 +0200 Subject: [PATCH 005/104] drm/tegra: dpaux: Fix error handling The devm_pinctrl_register() function returns an error pointer or a valid handle. So checking for NULL here is pointless and can never trigger. Check the returned value with IS_ERR instead and propagate this value as done in the other functions which call devm_pinctrl_register(). Fixes: 0751bb5c44fe ("drm/tegra: dpaux: Add pinctrl support") Signed-off-by: Christophe JAILLET Acked-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dpaux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 059f409556d5..2fde44c3a1b3 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -539,9 +539,9 @@ static int tegra_dpaux_probe(struct platform_device *pdev) dpaux->desc.owner = THIS_MODULE; dpaux->pinctrl = devm_pinctrl_register(&pdev->dev, &dpaux->desc, dpaux); - if (!dpaux->pinctrl) { + if (IS_ERR(dpaux->pinctrl)) { dev_err(&pdev->dev, "failed to register pincontrol\n"); - return -ENODEV; + return PTR_ERR(dpaux->pinctrl); } #endif /* enable and clear all interrupts */ From 87ba3e15fb6e94d8dcce838b5de71814b2d1a768 Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Sun, 3 Jul 2016 08:18:57 +0200 Subject: [PATCH 006/104] drm/tegra: Fix error handling It is likely that checking 'gr3d->clk_secondary' instead of 'gr3d->clk' is expected here. Signed-off-by: Christophe JAILLET Reviewed-by: Alexandre Courbot Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/gr3d.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index 0b3f2b977ba0..13f0d1b7cd98 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -268,9 +268,9 @@ static int gr3d_probe(struct platform_device *pdev) if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) { gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2"); - if (IS_ERR(gr3d->clk)) { + if (IS_ERR(gr3d->clk_secondary)) { dev_err(&pdev->dev, "cannot get secondary clock\n"); - return PTR_ERR(gr3d->clk); + return PTR_ERR(gr3d->clk_secondary); } gr3d->rst_secondary = devm_reset_control_get(&pdev->dev, From 4141e7448b501227967ff274af5f4eadadb6068b Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Sat, 24 Sep 2016 22:07:30 +0200 Subject: [PATCH 007/104] drm/tegra: sor: No need to free devm_ allocated memory Memory for the brick clock is allocated by devm_kzalloc(), so there is no need here to free it explicitly. The only function that calls tegra_clk_sor_brick_register() is the probe function and it correctly checks and handles the return value, which, on failure, will cause devm_ allocated memory to be freed automatically. Signed-off-by: Christophe JAILLET Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/sor.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 74d0540b8d4c..a8f528925009 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -349,8 +349,6 @@ static struct clk *tegra_clk_sor_brick_register(struct tegra_sor *sor, brick->hw.init = &init; clk = devm_clk_register(sor->dev, &brick->hw); - if (IS_ERR(clk)) - kfree(brick); return clk; } From cc09cb6da9b0eefe4b4e47a73170a349c4cf3426 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 30 Oct 2016 16:50:29 +0100 Subject: [PATCH 008/104] drm/tegra: gem: Remove some dead code dma_buf_map_attachment() never returns NULL, so there is no need to check for it. Signed-off-by: Christophe JAILLET Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/gem.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 95e622e31931..19bf9cdf1f11 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -318,11 +318,6 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm, get_dma_buf(buf); bo->sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE); - if (!bo->sgt) { - err = -ENOMEM; - goto detach; - } - if (IS_ERR(bo->sgt)) { err = PTR_ERR(bo->sgt); goto detach; From f08ef2d1a1a9aaa756823e847f9eb74f3658393a Mon Sep 17 00:00:00 2001 From: Arto Merilainen Date: Tue, 8 Nov 2016 19:51:32 +0200 Subject: [PATCH 009/104] gpu: host1x: Store device address to all bufs Currently job pinning is optimized to handle only the first buffer using a certain host1x_bo object and all subsequent buffers using the same host1x_bo are considered done. In most cases this is correct, however, in case the same host1x_bo is used in multiple gathers inside the same job, we skip also storing the device address (physical or iova) to this buffer. This patch reworks the host1x_job_pin() to store the device address to all gathers. Signed-off-by: Andrew Chew Signed-off-by: Arto Merilainen Signed-off-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/gpu/host1x/job.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index a91b7c4a6110..92c3df933303 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -1,7 +1,7 @@ /* * Tegra host1x Job * - * Copyright (c) 2010-2013, NVIDIA Corporation. + * Copyright (c) 2010-2015, NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -539,9 +539,12 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev) g->base = job->gather_addr_phys[i]; - for (j = i + 1; j < job->num_gathers; j++) - if (job->gathers[j].bo == g->bo) + for (j = i + 1; j < job->num_gathers; j++) { + if (job->gathers[j].bo == g->bo) { job->gathers[j].handled = true; + job->gathers[j].base = g->base; + } + } err = do_relocs(job, g->bo); if (err) From d4b5781890b9329b9e7720f14d3eeb5661348535 Mon Sep 17 00:00:00 2001 From: Arto Merilainen Date: Tue, 8 Nov 2016 19:51:33 +0200 Subject: [PATCH 010/104] gpu: host1x: Add locking to syncpt Currently syncpoints are not locked by mutex and this causes races if we are aggressively freeing and allocating syncpoints. This patch adds missing mutex protection to syncpoint structures. Signed-off-by: Arto Merilainen Reviewed-by: Shridhar Rasal Signed-off-by: Mikko Perttunen [treding@nvidia.com: use better label names, don't reset local variable] Signed-off-by: Thierry Reding --- drivers/gpu/host1x/dev.h | 3 ++- drivers/gpu/host1x/syncpt.c | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 5220510f39da..06dd4f85125f 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, NVIDIA Corporation. + * Copyright (c) 2012-2015, NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -120,6 +120,7 @@ struct host1x { struct host1x_syncpt *nop_sp; + struct mutex syncpt_mutex; struct mutex chlist_mutex; struct host1x_channel chlist; unsigned long allocated_channels; diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index 95589328ad52..25c11a85050b 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -1,7 +1,7 @@ /* * Tegra host1x Syncpoints * - * Copyright (c) 2010-2013, NVIDIA Corporation. + * Copyright (c) 2010-2015, NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -61,22 +61,24 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, struct host1x_syncpt *sp = host->syncpt; char *name; + mutex_lock(&host->syncpt_mutex); + for (i = 0; i < host->info->nb_pts && sp->name; i++, sp++) ; if (i >= host->info->nb_pts) - return NULL; + goto unlock; if (flags & HOST1X_SYNCPT_HAS_BASE) { sp->base = host1x_syncpt_base_request(host); if (!sp->base) - return NULL; + goto unlock; } name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id, dev ? dev_name(dev) : NULL); if (!name) - return NULL; + goto free_base; sp->dev = dev; sp->name = name; @@ -86,7 +88,15 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, else sp->client_managed = false; + mutex_unlock(&host->syncpt_mutex); return sp; + +free_base: + host1x_syncpt_base_free(sp->base); + sp->base = NULL; +unlock: + mutex_unlock(&host->syncpt_mutex); + return NULL; } u32 host1x_syncpt_id(struct host1x_syncpt *sp) @@ -378,6 +388,7 @@ int host1x_syncpt_init(struct host1x *host) for (i = 0; i < host->info->nb_bases; i++) bases[i].id = i; + mutex_init(&host->syncpt_mutex); host->syncpt = syncpt; host->bases = bases; @@ -405,12 +416,16 @@ void host1x_syncpt_free(struct host1x_syncpt *sp) if (!sp) return; + mutex_lock(&sp->host->syncpt_mutex); + host1x_syncpt_base_free(sp->base); kfree(sp->name); sp->base = NULL; sp->dev = NULL; sp->name = NULL; sp->client_managed = false; + + mutex_unlock(&sp->host->syncpt_mutex); } EXPORT_SYMBOL(host1x_syncpt_free); From 7ecada3cc44798c88d2c3deed38746b9a7a9b746 Mon Sep 17 00:00:00 2001 From: Arto Merilainen Date: Tue, 8 Nov 2016 19:51:34 +0200 Subject: [PATCH 011/104] drm/tegra: Support kernel mappings with IOMMU host1x command buffer patching requires that the buffer object can be mapped into kernel address space. However, the recent addition of IOMMU support did not account for this requirement. Therefore host1x engines cannot be used if IOMMU is enabled. This patch implements kmap, kunmap, mmap and munmap functions to host1x buffer objects. Signed-off-by: Arto Merilainen Signed-off-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/gem.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 19bf9cdf1f11..25083729a89c 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -2,7 +2,7 @@ * NVIDIA Tegra DRM GEM helper functions * * Copyright (C) 2012 Sascha Hauer, Pengutronix - * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved. + * Copyright (C) 2013-2015 NVIDIA CORPORATION, All rights reserved. * * Based on the GEM/CMA helpers * @@ -47,23 +47,51 @@ static void *tegra_bo_mmap(struct host1x_bo *bo) { struct tegra_bo *obj = host1x_to_tegra_bo(bo); - return obj->vaddr; + if (obj->vaddr) + return obj->vaddr; + else if (obj->gem.import_attach) + return dma_buf_vmap(obj->gem.import_attach->dmabuf); + else + return vmap(obj->pages, obj->num_pages, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); } static void tegra_bo_munmap(struct host1x_bo *bo, void *addr) { + struct tegra_bo *obj = host1x_to_tegra_bo(bo); + + if (obj->vaddr) + return; + else if (obj->gem.import_attach) + dma_buf_vunmap(obj->gem.import_attach->dmabuf, addr); + else + vunmap(addr); } static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page) { struct tegra_bo *obj = host1x_to_tegra_bo(bo); - return obj->vaddr + page * PAGE_SIZE; + if (obj->vaddr) + return obj->vaddr + page * PAGE_SIZE; + else if (obj->gem.import_attach) + return dma_buf_kmap(obj->gem.import_attach->dmabuf, page); + else + return vmap(obj->pages + page, 1, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); } static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page, void *addr) { + struct tegra_bo *obj = host1x_to_tegra_bo(bo); + + if (obj->vaddr) + return; + else if (obj->gem.import_attach) + dma_buf_kunmap(obj->gem.import_attach->dmabuf, page, addr); + else + vunmap(addr); } static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo) From 585ee0f27ef7b8db46807b960388b7e58b60766d Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Tue, 8 Nov 2016 19:51:35 +0200 Subject: [PATCH 012/104] drm/tegra: Set sgt pointer in BO pin Fix tegra_bo_pin() to set the parameter sgt pointer. host1x job pinning requires the sgt to determine physical memory addresses of gathers. Signed-off-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/gem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 25083729a89c..c08e5279eeac 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -36,6 +36,8 @@ static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt) { struct tegra_bo *obj = host1x_to_tegra_bo(bo); + *sgt = obj->sgt; + return obj->paddr; } From e992faee1f82cebf39c65b340d7591ab1aa8c742 Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Mon, 21 Nov 2016 17:08:14 +0800 Subject: [PATCH 013/104] drm/i915/gvt: fix missing init param.primary Initiate param.primary to 1. We should be primary currently. Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/vgpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 4f64845d8a4c..536d2b9d5777 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -378,6 +378,7 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, struct intel_vgpu *vgpu; param.handle = 0; + param.primary = 1; param.low_gm_sz = type->low_gm_size; param.high_gm_sz = type->high_gm_size; param.fence_sz = type->fence; From 550dd77ebb6360120269d9a7102ae2c0cea41290 Mon Sep 17 00:00:00 2001 From: Xiaoguang Chen Date: Thu, 24 Nov 2016 13:13:00 +0800 Subject: [PATCH 014/104] drm/i915/gvt: fix getting 64bit bar size error For 64bit bar while reading the higher 32bit the value should be returned directly. In the current implementation the higher 32bit value was discarded and not written to the cfg space of vgpu which lead to an incorrect bar size. Signed-off-by: Xiaoguang Chen Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gvt.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 3d4223e8ebe3..b1a7c8dd4b5f 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -361,6 +361,8 @@ static inline void intel_vgpu_write_pci_bar(struct intel_vgpu *vgpu, * leave the bit 3 - bit 0 unchanged. */ *pval = (val & GENMASK(31, 4)) | (*pval & GENMASK(3, 0)); + } else { + *pval = val; } } From 53d6f812c0dbf1c9cad89b1c2118e61c13ca9677 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Thu, 24 Nov 2016 15:55:49 +0800 Subject: [PATCH 015/104] drm/i915/gvt: fix lock not released bug for dispatch_workload() err path Need to be careful to release struct_mutext when request alloc failed and take consistent handling for return status as with normal go out path. Ensure to check correct workload request in complete path too. v2: Add Fixes note Fixes: 90d27a1b180e ("drm/i915/gvt: fix deadlock in workload_thread") Reported-by: Dan Carpenter Cc: Dan Carpenter Cc: Pei Zhang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/scheduler.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index f898df38dd9a..4db242250235 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -177,8 +177,8 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); if (IS_ERR(rq)) { gvt_err("fail to allocate gem request\n"); - workload->status = PTR_ERR(rq); - return workload->status; + ret = PTR_ERR(rq); + goto out; } gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq); @@ -212,7 +212,8 @@ out: if (ret) workload->status = ret; - i915_add_request_no_flush(rq); + if (!IS_ERR_OR_NULL(rq)) + i915_add_request_no_flush(rq); mutex_unlock(&dev_priv->drm.struct_mutex); return ret; } @@ -460,7 +461,8 @@ complete: complete_current_workload(gvt, ring_id); - i915_gem_request_put(fetch_and_zero(&workload->req)); + if (workload->req) + i915_gem_request_put(fetch_and_zero(&workload->req)); if (need_force_wake) intel_uncore_forcewake_put(gvt->dev_priv, From 39a5019a2c13580f21efc756babccb4c03b6a8ce Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 19 Oct 2016 17:32:20 -0700 Subject: [PATCH 016/104] drm/fsl-dcu: unload driver before disabling clocks Use drm_put_dev to unload the driver before disabling clocks. Otherwise the driver might read a register during unload which leads to an external abort. Signed-off-by: Stefan Agner --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 0b0d1cb11641..30c46a80a540 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -428,9 +428,9 @@ static int fsl_dcu_drm_remove(struct platform_device *pdev) { struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev); + drm_put_dev(fsl_dev->drm); clk_disable_unprepare(fsl_dev->clk); clk_unregister(fsl_dev->pix_clk); - drm_put_dev(fsl_dev->drm); return 0; } From 39c74b515bc2172597f6a85c7310cbf348d66a82 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 19 Oct 2016 17:32:21 -0700 Subject: [PATCH 017/104] drm/fsl-dcu: disable outputs before unloading driver Make sure that all outputs are disabled before unloading the DRM driver. Otherwise vblank handling is not shut down properly and warnings such as this appear: WARNING: CPU: 0 PID: 540 at drivers/gpu/drm/drm_irq.c:339 drm_vblank_cleanup+0x5c/0x94 Signed-off-by: Stefan Agner --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 30c46a80a540..f8313f2b113a 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -108,6 +108,7 @@ static int fsl_dcu_unload(struct drm_device *dev) { struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; + drm_crtc_force_disable_all(dev); drm_kms_helper_poll_fini(dev); if (fsl_dev->fbdev) From 54ac0a0f72cdf66634c1321addd32eaadb0f022d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 16 Nov 2016 13:38:32 -0200 Subject: [PATCH 018/104] drm/fsl-dcu: Remove unneeded NULL check devm_ioremap_resource() performs NULL check for the 'res' argument, so remove the unneeded check. Signed-off-by: Fabio Estevam Signed-off-by: Stefan Agner --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index f8313f2b113a..2ecbb4942b80 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -337,11 +337,6 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev) fsl_dev->soc = id->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "could not get memory IO resource\n"); - return -ENODEV; - } - base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); From 238e4f44c05644089968fbd1a701a6be58ddb546 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 16 Nov 2016 13:38:33 -0200 Subject: [PATCH 019/104] drm/fsl-dcu: Propagate the real error code In case of platform_get_irq() failure, let's propagate the real error code, instead of a 'fake' one. Signed-off-by: Fabio Estevam Signed-off-by: Stefan Agner --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 2ecbb4942b80..f242e64c76ca 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -346,7 +346,7 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev) fsl_dev->irq = platform_get_irq(pdev, 0); if (fsl_dev->irq < 0) { dev_err(dev, "failed to get irq\n"); - return -ENXIO; + return fsl_dev->irq; } fsl_dev->regmap = devm_regmap_init_mmio(dev, base, From c162215f570567b3a264d8e1abb50971d78bbaf3 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Nov 2016 17:14:06 -0800 Subject: [PATCH 020/104] drm/fsl-dcu: remove separate compilation unit for fbdev emulation The separate file fsl_dcu_drm_fbdev.c only initialized fbdev emulation which is a one-line operation. There is not much more code on sight which justifies a separate file, hence call the initialization helper directly from the drv file. Signed-off-by: Stefan Agner --- drivers/gpu/drm/fsl-dcu/Makefile | 1 - drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 2 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h | 1 - drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c | 23 --------------------- 4 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c diff --git a/drivers/gpu/drm/fsl-dcu/Makefile b/drivers/gpu/drm/fsl-dcu/Makefile index b35a292287f3..aca34f656bea 100644 --- a/drivers/gpu/drm/fsl-dcu/Makefile +++ b/drivers/gpu/drm/fsl-dcu/Makefile @@ -3,6 +3,5 @@ fsl-dcu-drm-y := fsl_dcu_drm_drv.o \ fsl_dcu_drm_rgb.o \ fsl_dcu_drm_plane.o \ fsl_dcu_drm_crtc.o \ - fsl_dcu_drm_fbdev.o \ fsl_tcon.o obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu-drm.o diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index f242e64c76ca..736451616ce4 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -87,7 +87,7 @@ static int fsl_dcu_load(struct drm_device *dev, unsigned long flags) goto done; dev->irq_enabled = true; - fsl_dcu_fbdev_init(dev); + fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1); return 0; done: diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h index 3b371fe7491e..e9e9aeecf2eb 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h @@ -197,7 +197,6 @@ struct fsl_dcu_drm_device { struct drm_atomic_state *state; }; -void fsl_dcu_fbdev_init(struct drm_device *dev); int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev); #endif /* __FSL_DCU_DRM_DRV_H__ */ diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c deleted file mode 100644 index 8b8b819ea704..000000000000 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2015 Freescale Semiconductor, Inc. - * - * Freescale DCU drm device driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include - -#include "fsl_dcu_drm_drv.h" - -/* initialize fbdev helper */ -void fsl_dcu_fbdev_init(struct drm_device *dev) -{ - struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev); - - fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1); -} From 73fe26a48659abd2b85d2f87d3cf2400ddb313d7 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 16 Nov 2016 17:23:27 -0800 Subject: [PATCH 021/104] drm/fsl-dcu: introduce kernel parameter to specify fbdev depth Add a kernel parameter legancyfb_depth (like the i.MX drm driver) to control the legancy fbdev depth. Default to the so far hard coded depth of 24-bit. Currently changing the framebuffer depth is not possible from user space when using the fbdev emulation layer... This provides a rudimentary mechanism to change depth without having to change kernel code. Signed-off-by: Stefan Agner --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 736451616ce4..58ccacaf5a4e 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -32,6 +32,9 @@ #include "fsl_dcu_drm_drv.h" #include "fsl_tcon.h" +static int legacyfb_depth = 24; +module_param(legacyfb_depth, int, 0444); + static bool fsl_dcu_drm_is_volatile_reg(struct device *dev, unsigned int reg) { if (reg == DCU_INT_STATUS || reg == DCU_UPDATE_MODE) @@ -87,7 +90,18 @@ static int fsl_dcu_load(struct drm_device *dev, unsigned long flags) goto done; dev->irq_enabled = true; - fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1); + if (legacyfb_depth != 16 && legacyfb_depth != 24 && + legacyfb_depth != 32) { + dev_warn(dev->dev, + "Invalid legacyfb_depth. Defaulting to 24bpp\n"); + legacyfb_depth = 24; + } + fsl_dev->fbdev = drm_fbdev_cma_init(dev, legacyfb_depth, 1, 1); + if (IS_ERR(fsl_dev->fbdev)) { + ret = PTR_ERR(fsl_dev->fbdev); + fsl_dev->fbdev = NULL; + goto done; + } return 0; done: From 26fc78f6fef39b9d7a15def5e7e9826ff68303f4 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Thu, 24 Nov 2016 12:11:55 -0600 Subject: [PATCH 022/104] drm/vc4: Fix race between page flip completion event and clean-up There was a small window where a userspace program could submit a pageflip after receiving a pageflip completion event yet still receive EBUSY. Signed-off-by: Derek Foreman Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt Reviewed-by: Daniel Stone --- drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++++++ drivers/gpu/drm/vc4/vc4_drv.h | 1 + drivers/gpu/drm/vc4/vc4_kms.c | 33 +++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 7f08d681a74b..82f914af4156 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -669,6 +669,14 @@ void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id) CRTC_WRITE(PV_INTEN, 0); } +/* Must be called with the event lock held */ +bool vc4_event_pending(struct drm_crtc *crtc) +{ + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + + return !!vc4_crtc->event; +} + static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) { struct drm_crtc *crtc = &vc4_crtc->base; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index fef172804345..b3064e2e79c1 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -442,6 +442,7 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg); extern struct platform_driver vc4_crtc_driver; int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id); void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id); +bool vc4_event_pending(struct drm_crtc *crtc); int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, unsigned int flags, int *vpos, int *hpos, diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index c1f65c6c8e60..67af2af70af0 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -119,17 +119,34 @@ static int vc4_atomic_commit(struct drm_device *dev, /* Make sure that any outstanding modesets have finished. */ if (nonblock) { - ret = down_trylock(&vc4->async_modeset); - if (ret) { + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + unsigned long flags; + bool busy = false; + + /* + * If there's an undispatched event to send then we're + * obviously still busy. If there isn't, then we can + * unconditionally wait for the semaphore because it + * shouldn't be contended (for long). + * + * This is to prevent a race where queuing a new flip + * from userspace immediately on receipt of an event + * beats our clean-up and returns EBUSY. + */ + spin_lock_irqsave(&dev->event_lock, flags); + for_each_crtc_in_state(state, crtc, crtc_state, i) + busy |= vc4_event_pending(crtc); + spin_unlock_irqrestore(&dev->event_lock, flags); + if (busy) { kfree(c); return -EBUSY; } - } else { - ret = down_interruptible(&vc4->async_modeset); - if (ret) { - kfree(c); - return ret; - } + } + ret = down_interruptible(&vc4->async_modeset); + if (ret) { + kfree(c); + return ret; } ret = drm_atomic_helper_prepare_planes(dev, state); From bbbe775ec5b5dace43a35886da9924837da09ddd Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 10 Nov 2016 15:29:37 +0100 Subject: [PATCH 023/104] drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter Signed-off-by: Neil Armstrong --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/meson/Kconfig | 9 + drivers/gpu/drm/meson/Makefile | 4 + drivers/gpu/drm/meson/meson_canvas.c | 68 ++ drivers/gpu/drm/meson/meson_canvas.h | 42 + drivers/gpu/drm/meson/meson_crtc.c | 208 ++++ drivers/gpu/drm/meson/meson_crtc.h | 32 + drivers/gpu/drm/meson/meson_drv.c | 343 ++++++ drivers/gpu/drm/meson/meson_drv.h | 59 + drivers/gpu/drm/meson/meson_plane.c | 230 ++++ drivers/gpu/drm/meson/meson_plane.h | 30 + drivers/gpu/drm/meson/meson_registers.h | 1395 +++++++++++++++++++++++ drivers/gpu/drm/meson/meson_vclk.c | 167 +++ drivers/gpu/drm/meson/meson_vclk.h | 34 + drivers/gpu/drm/meson/meson_venc.c | 254 +++++ drivers/gpu/drm/meson/meson_venc.h | 72 ++ drivers/gpu/drm/meson/meson_venc_cvbs.c | 293 +++++ drivers/gpu/drm/meson/meson_venc_cvbs.h | 41 + drivers/gpu/drm/meson/meson_viu.c | 331 ++++++ drivers/gpu/drm/meson/meson_viu.h | 64 ++ drivers/gpu/drm/meson/meson_vpp.c | 162 +++ drivers/gpu/drm/meson/meson_vpp.h | 35 + 23 files changed, 3876 insertions(+) create mode 100644 drivers/gpu/drm/meson/Kconfig create mode 100644 drivers/gpu/drm/meson/Makefile create mode 100644 drivers/gpu/drm/meson/meson_canvas.c create mode 100644 drivers/gpu/drm/meson/meson_canvas.h create mode 100644 drivers/gpu/drm/meson/meson_crtc.c create mode 100644 drivers/gpu/drm/meson/meson_crtc.h create mode 100644 drivers/gpu/drm/meson/meson_drv.c create mode 100644 drivers/gpu/drm/meson/meson_drv.h create mode 100644 drivers/gpu/drm/meson/meson_plane.c create mode 100644 drivers/gpu/drm/meson/meson_plane.h create mode 100644 drivers/gpu/drm/meson/meson_registers.h create mode 100644 drivers/gpu/drm/meson/meson_vclk.c create mode 100644 drivers/gpu/drm/meson/meson_vclk.h create mode 100644 drivers/gpu/drm/meson/meson_venc.c create mode 100644 drivers/gpu/drm/meson/meson_venc.h create mode 100644 drivers/gpu/drm/meson/meson_venc_cvbs.c create mode 100644 drivers/gpu/drm/meson/meson_venc_cvbs.h create mode 100644 drivers/gpu/drm/meson/meson_viu.c create mode 100644 drivers/gpu/drm/meson/meson_viu.h create mode 100644 drivers/gpu/drm/meson/meson_vpp.c create mode 100644 drivers/gpu/drm/meson/meson_vpp.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 483059a22b1b..344ced6483f2 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -223,6 +223,8 @@ source "drivers/gpu/drm/hisilicon/Kconfig" source "drivers/gpu/drm/mediatek/Kconfig" +source "drivers/gpu/drm/meson/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACY diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 25c720454017..47e7c45b1fc0 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_DRM_TEGRA) += tegra/ obj-$(CONFIG_DRM_STI) += sti/ obj-$(CONFIG_DRM_IMX) += imx/ obj-$(CONFIG_DRM_MEDIATEK) += mediatek/ +obj-$(CONFIG_DRM_MESON) += meson/ obj-y += i2c/ obj-y += panel/ obj-y += bridge/ diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig new file mode 100644 index 000000000000..99719afcc77f --- /dev/null +++ b/drivers/gpu/drm/meson/Kconfig @@ -0,0 +1,9 @@ +config DRM_MESON + tristate "DRM Support for Amlogic Meson Display Controller" + depends on DRM && OF && (ARM || ARM64) + depends on ARCH_MESON || COMPILE_TEST + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER + select VIDEOMODE_HELPERS + select REGMAP_MMIO diff --git a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile new file mode 100644 index 000000000000..2591978b8aad --- /dev/null +++ b/drivers/gpu/drm/meson/Makefile @@ -0,0 +1,4 @@ +meson-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o +meson-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o + +obj-$(CONFIG_DRM_MESON) += meson.o diff --git a/drivers/gpu/drm/meson/meson_canvas.c b/drivers/gpu/drm/meson/meson_canvas.c new file mode 100644 index 000000000000..4109e36c297f --- /dev/null +++ b/drivers/gpu/drm/meson/meson_canvas.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include "meson_drv.h" +#include "meson_canvas.h" +#include "meson_registers.h" + +/* + * CANVAS is a memory zone where physical memory frames information + * are stored for the VIU to scanout. + */ + +/* DMC Registers */ +#define DMC_CAV_LUT_DATAL 0x48 /* 0x12 offset in data sheet */ +#define CANVAS_WIDTH_LBIT 29 +#define CANVAS_WIDTH_LWID 3 +#define DMC_CAV_LUT_DATAH 0x4c /* 0x13 offset in data sheet */ +#define CANVAS_WIDTH_HBIT 0 +#define CANVAS_HEIGHT_BIT 9 +#define CANVAS_BLKMODE_BIT 24 +#define DMC_CAV_LUT_ADDR 0x50 /* 0x14 offset in data sheet */ +#define CANVAS_LUT_WR_EN (0x2 << 8) +#define CANVAS_LUT_RD_EN (0x1 << 8) + +void meson_canvas_setup(struct meson_drm *priv, + uint32_t canvas_index, uint32_t addr, + uint32_t stride, uint32_t height, + unsigned int wrap, + unsigned int blkmode) +{ + unsigned int val; + + regmap_write(priv->dmc, DMC_CAV_LUT_DATAL, + (((addr + 7) >> 3)) | + (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT)); + + regmap_write(priv->dmc, DMC_CAV_LUT_DATAH, + ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) << + CANVAS_WIDTH_HBIT) | + (height << CANVAS_HEIGHT_BIT) | + (wrap << 22) | + (blkmode << CANVAS_BLKMODE_BIT)); + + regmap_write(priv->dmc, DMC_CAV_LUT_ADDR, + CANVAS_LUT_WR_EN | canvas_index); + + /* Force a read-back to make sure everything is flushed. */ + regmap_read(priv->dmc, DMC_CAV_LUT_DATAH, &val); +} diff --git a/drivers/gpu/drm/meson/meson_canvas.h b/drivers/gpu/drm/meson/meson_canvas.h new file mode 100644 index 000000000000..af1759da4b27 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_canvas.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* Canvas LUT Memory */ + +#ifndef __MESON_CANVAS_H +#define __MESON_CANVAS_H + +#define MESON_CANVAS_ID_OSD1 0x4e + +/* Canvas configuration. */ +#define MESON_CANVAS_WRAP_NONE 0x00 +#define MESON_CANVAS_WRAP_X 0x01 +#define MESON_CANVAS_WRAP_Y 0x02 + +#define MESON_CANVAS_BLKMODE_LINEAR 0x00 +#define MESON_CANVAS_BLKMODE_32x32 0x01 +#define MESON_CANVAS_BLKMODE_64x64 0x02 + +void meson_canvas_setup(struct meson_drm *priv, + uint32_t canvas_index, uint32_t addr, + uint32_t stride, uint32_t height, + unsigned int wrap, + unsigned int blkmode); + +#endif /* __MESON_CANVAS_H */ diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c new file mode 100644 index 000000000000..749770e5c65f --- /dev/null +++ b/drivers/gpu/drm/meson/meson_crtc.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Written by: + * Jasper St. Pierre + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "meson_crtc.h" +#include "meson_plane.h" +#include "meson_vpp.h" +#include "meson_viu.h" +#include "meson_registers.h" + +/* CRTC definition */ + +struct meson_crtc { + struct drm_crtc base; + struct drm_pending_vblank_event *event; + struct meson_drm *priv; +}; +#define to_meson_crtc(x) container_of(x, struct meson_crtc, base) + +/* CRTC */ + +static const struct drm_crtc_funcs meson_crtc_funcs = { + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .destroy = drm_crtc_cleanup, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .set_config = drm_atomic_helper_set_config, +}; + +static void meson_crtc_enable(struct drm_crtc *crtc) +{ + struct meson_crtc *meson_crtc = to_meson_crtc(crtc); + struct drm_plane *plane = meson_crtc->priv->primary_plane; + struct meson_drm *priv = meson_crtc->priv; + + /* Enable VPP Postblend */ + writel(plane->state->crtc_w, + priv->io_base + _REG(VPP_POSTBLEND_H_SIZE)); + + writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE, + priv->io_base + _REG(VPP_MISC)); + + priv->viu.osd1_enabled = true; +} + +static void meson_crtc_disable(struct drm_crtc *crtc) +{ + struct meson_crtc *meson_crtc = to_meson_crtc(crtc); + struct meson_drm *priv = meson_crtc->priv; + + priv->viu.osd1_enabled = false; + + /* Disable VPP Postblend */ + writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0, + priv->io_base + _REG(VPP_MISC)); + + if (crtc->state->event && !crtc->state->active) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&crtc->dev->event_lock); + + crtc->state->event = NULL; + } +} + +static void meson_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct meson_crtc *meson_crtc = to_meson_crtc(crtc); + unsigned long flags; + + if (crtc->state->event) { + WARN_ON(drm_crtc_vblank_get(crtc) != 0); + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + meson_crtc->event = crtc->state->event; + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + crtc->state->event = NULL; + } +} + +static void meson_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + struct meson_crtc *meson_crtc = to_meson_crtc(crtc); + struct meson_drm *priv = meson_crtc->priv; + + if (priv->viu.osd1_enabled) + priv->viu.osd1_commit = true; +} + +static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = { + .enable = meson_crtc_enable, + .disable = meson_crtc_disable, + .atomic_begin = meson_crtc_atomic_begin, + .atomic_flush = meson_crtc_atomic_flush, +}; + +void meson_crtc_irq(struct meson_drm *priv) +{ + struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc); + unsigned long flags; + + /* Update the OSD registers */ + if (priv->viu.osd1_enabled && priv->viu.osd1_commit) { + writel_relaxed(priv->viu.osd1_ctrl_stat, + priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); + writel_relaxed(priv->viu.osd1_blk0_cfg[0], + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0)); + writel_relaxed(priv->viu.osd1_blk0_cfg[1], + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1)); + writel_relaxed(priv->viu.osd1_blk0_cfg[2], + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2)); + writel_relaxed(priv->viu.osd1_blk0_cfg[3], + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3)); + writel_relaxed(priv->viu.osd1_blk0_cfg[4], + priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4)); + + /* If output is interlace, make use of the Scaler */ + if (priv->viu.osd1_interlace) { + struct drm_plane *plane = priv->primary_plane; + struct drm_plane_state *state = plane->state; + struct drm_rect dest = { + .x1 = state->crtc_x, + .y1 = state->crtc_y, + .x2 = state->crtc_x + state->crtc_w, + .y2 = state->crtc_y + state->crtc_h, + }; + + meson_vpp_setup_interlace_vscaler_osd1(priv, &dest); + } else + meson_vpp_disable_interlace_vscaler_osd1(priv); + + /* Enable OSD1 */ + writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND, + priv->io_base + _REG(VPP_MISC)); + + priv->viu.osd1_commit = false; + } + + drm_crtc_handle_vblank(priv->crtc); + + spin_lock_irqsave(&priv->drm->event_lock, flags); + if (meson_crtc->event) { + drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event); + drm_crtc_vblank_put(priv->crtc); + meson_crtc->event = NULL; + } + spin_unlock_irqrestore(&priv->drm->event_lock, flags); +} + +int meson_crtc_create(struct meson_drm *priv) +{ + struct meson_crtc *meson_crtc; + struct drm_crtc *crtc; + int ret; + + meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc), + GFP_KERNEL); + if (!meson_crtc) + return -ENOMEM; + + meson_crtc->priv = priv; + crtc = &meson_crtc->base; + ret = drm_crtc_init_with_planes(priv->drm, crtc, + priv->primary_plane, NULL, + &meson_crtc_funcs, "meson_crtc"); + if (ret) { + dev_err(priv->drm->dev, "Failed to init CRTC\n"); + return ret; + } + + drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs); + + priv->crtc = crtc; + + return 0; +} diff --git a/drivers/gpu/drm/meson/meson_crtc.h b/drivers/gpu/drm/meson/meson_crtc.h new file mode 100644 index 000000000000..b62b9e51764d --- /dev/null +++ b/drivers/gpu/drm/meson/meson_crtc.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Written by: + * Jasper St. Pierre + */ + +#ifndef __MESON_CRTC_H +#define __MESON_CRTC_H + +#include "meson_drv.h" + +int meson_crtc_create(struct meson_drm *priv); + +void meson_crtc_irq(struct meson_drm *priv); + +#endif /* __MESON_CRTC_H */ diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c new file mode 100644 index 000000000000..ff1f6019b97b --- /dev/null +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Written by: + * Jasper St. Pierre + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "meson_drv.h" +#include "meson_plane.h" +#include "meson_crtc.h" +#include "meson_venc_cvbs.h" + +#include "meson_vpp.h" +#include "meson_viu.h" +#include "meson_venc.h" +#include "meson_canvas.h" +#include "meson_registers.h" + +#define DRIVER_NAME "meson" +#define DRIVER_DESC "Amlogic Meson DRM driver" + +/* + * Video Processing Unit + * + * VPU Handles the Global Video Processing, it includes management of the + * clocks gates, blocks reset lines and power domains. + * + * What is missing : + * - Full reset of entire video processing HW blocks + * - Scaling and setup of the VPU clock + * - Bus clock gates + * - Powering up video processing HW blocks + * - Powering Up HDMI controller and PHY + */ + +static void meson_fb_output_poll_changed(struct drm_device *dev) +{ + struct meson_drm *priv = dev->dev_private; + + drm_fbdev_cma_hotplug_event(priv->fbdev); +} + +static const struct drm_mode_config_funcs meson_mode_config_funcs = { + .output_poll_changed = meson_fb_output_poll_changed, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, + .fb_create = drm_fb_cma_create, +}; + +static int meson_enable_vblank(struct drm_device *dev, unsigned int crtc) +{ + struct meson_drm *priv = dev->dev_private; + + meson_venc_enable_vsync(priv); + + return 0; +} + +static void meson_disable_vblank(struct drm_device *dev, unsigned int crtc) +{ + struct meson_drm *priv = dev->dev_private; + + meson_venc_disable_vsync(priv); +} + +static irqreturn_t meson_irq(int irq, void *arg) +{ + struct drm_device *dev = arg; + struct meson_drm *priv = dev->dev_private; + + (void)readl_relaxed(priv->io_base + _REG(VENC_INTFLAG)); + + meson_crtc_irq(priv); + + return IRQ_HANDLED; +} + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif + .poll = drm_poll, + .read = drm_read, + .llseek = no_llseek, + .mmap = drm_gem_cma_mmap, +}; + +static struct drm_driver meson_driver = { + .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | + DRIVER_MODESET | DRIVER_PRIME | + DRIVER_ATOMIC, + + /* Vblank */ + .enable_vblank = meson_enable_vblank, + .disable_vblank = meson_disable_vblank, + .get_vblank_counter = drm_vblank_no_hw_counter, + + /* IRQ */ + .irq_handler = meson_irq, + + /* PRIME Ops */ + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_vmap = drm_gem_cma_prime_vmap, + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, + .gem_prime_mmap = drm_gem_cma_prime_mmap, + + /* GEM Ops */ + .dumb_create = drm_gem_cma_dumb_create, + .dumb_destroy = drm_gem_dumb_destroy, + .dumb_map_offset = drm_gem_cma_dumb_map_offset, + .gem_free_object_unlocked = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + + /* Misc */ + .fops = &fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = "20161109", + .major = 1, + .minor = 0, +}; + +static bool meson_vpu_has_available_connectors(struct device *dev) +{ + struct device_node *ep, *remote; + + /* Parses each endpoint and check if remote exists */ + for_each_endpoint_of_node(dev->of_node, ep) { + /* If the endpoint node exists, consider it enabled */ + remote = of_graph_get_remote_port(ep); + if (remote) + return true; + } + + return false; +} + +static struct regmap_config meson_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x1000, +}; + +static int meson_drv_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct meson_drm *priv; + struct drm_device *drm; + struct resource *res; + void __iomem *regs; + int ret; + + /* Checks if an output connector is available */ + if (!meson_vpu_has_available_connectors(dev)) { + dev_err(dev, "No output connector available\n"); + return -ENODEV; + } + + drm = drm_dev_alloc(&meson_driver, dev); + if (IS_ERR(drm)) + return PTR_ERR(drm); + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto free_drm; + } + drm->dev_private = priv; + priv->drm = drm; + priv->dev = dev; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpu"); + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + priv->io_base = regs; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hhi"); + /* Simply ioremap since it may be a shared register zone */ + regs = devm_ioremap(dev, res->start, resource_size(res)); + if (!regs) + return -EADDRNOTAVAIL; + + priv->hhi = devm_regmap_init_mmio(dev, regs, + &meson_regmap_config); + if (IS_ERR(priv->hhi)) { + dev_err(&pdev->dev, "Couldn't create the HHI regmap\n"); + return PTR_ERR(priv->hhi); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmc"); + /* Simply ioremap since it may be a shared register zone */ + regs = devm_ioremap(dev, res->start, resource_size(res)); + if (!regs) + return -EADDRNOTAVAIL; + + priv->dmc = devm_regmap_init_mmio(dev, regs, + &meson_regmap_config); + if (IS_ERR(priv->dmc)) { + dev_err(&pdev->dev, "Couldn't create the DMC regmap\n"); + return PTR_ERR(priv->dmc); + } + + priv->vsync_irq = platform_get_irq(pdev, 0); + + drm_vblank_init(drm, 1); + drm_mode_config_init(drm); + + /* Encoder Initialization */ + + ret = meson_venc_cvbs_create(priv); + if (ret) + goto free_drm; + + /* Hardware Initialization */ + + meson_venc_init(priv); + meson_vpp_init(priv); + meson_viu_init(priv); + + ret = meson_plane_create(priv); + if (ret) + goto free_drm; + + ret = meson_crtc_create(priv); + if (ret) + goto free_drm; + + ret = drm_irq_install(drm, priv->vsync_irq); + if (ret) + goto free_drm; + + drm_mode_config_reset(drm); + drm->mode_config.max_width = 8192; + drm->mode_config.max_height = 8192; + drm->mode_config.funcs = &meson_mode_config_funcs; + + priv->fbdev = drm_fbdev_cma_init(drm, 32, + drm->mode_config.num_crtc, + drm->mode_config.num_connector); + if (IS_ERR(priv->fbdev)) { + ret = PTR_ERR(priv->fbdev); + goto free_drm; + } + + drm_kms_helper_poll_init(drm); + + platform_set_drvdata(pdev, priv); + + ret = drm_dev_register(drm, 0); + if (ret) + goto free_drm; + + return 0; + +free_drm: + drm_dev_unref(drm); + + return ret; +} + +static int meson_drv_remove(struct platform_device *pdev) +{ + struct drm_device *drm = dev_get_drvdata(&pdev->dev); + struct meson_drm *priv = drm->dev_private; + + drm_dev_unregister(drm); + drm_kms_helper_poll_fini(drm); + drm_fbdev_cma_fini(priv->fbdev); + drm_mode_config_cleanup(drm); + drm_vblank_cleanup(drm); + drm_dev_unref(drm); + + return 0; +} + +static const struct of_device_id dt_match[] = { + { .compatible = "amlogic,meson-gxbb-vpu" }, + { .compatible = "amlogic,meson-gxl-vpu" }, + { .compatible = "amlogic,meson-gxm-vpu" }, + {} +}; +MODULE_DEVICE_TABLE(of, dt_match); + +static struct platform_driver meson_drm_platform_driver = { + .probe = meson_drv_probe, + .remove = meson_drv_remove, + .driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME, + .of_match_table = dt_match, + }, +}; + +module_platform_driver(meson_drm_platform_driver); + +MODULE_AUTHOR("Jasper St. Pierre "); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h new file mode 100644 index 000000000000..6195327c51ca --- /dev/null +++ b/drivers/gpu/drm/meson/meson_drv.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __MESON_DRV_H +#define __MESON_DRV_H + +#include +#include +#include +#include + +struct meson_drm { + struct device *dev; + void __iomem *io_base; + struct regmap *hhi; + struct regmap *dmc; + int vsync_irq; + + struct drm_device *drm; + struct drm_crtc *crtc; + struct drm_fbdev_cma *fbdev; + struct drm_plane *primary_plane; + + /* Components Data */ + struct { + bool osd1_enabled; + bool osd1_interlace; + bool osd1_commit; + uint32_t osd1_ctrl_stat; + uint32_t osd1_blk0_cfg[5]; + } viu; + + struct { + unsigned int current_mode; + } venc; +}; + +static inline int meson_vpu_is_compatible(struct meson_drm *priv, + const char *compat) +{ + return of_device_is_compatible(priv->dev->of_node, compat); +} + +#endif /* __MESON_DRV_H */ diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c new file mode 100644 index 000000000000..4942ca090b46 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Written by: + * Jasper St. Pierre + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "meson_plane.h" +#include "meson_vpp.h" +#include "meson_viu.h" +#include "meson_canvas.h" +#include "meson_registers.h" + +struct meson_plane { + struct drm_plane base; + struct meson_drm *priv; +}; +#define to_meson_plane(x) container_of(x, struct meson_plane, base) + +static int meson_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct drm_crtc_state *crtc_state; + struct drm_rect clip = { 0, }; + + crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + clip.x2 = crtc_state->mode.hdisplay; + clip.y2 = crtc_state->mode.vdisplay; + + return drm_plane_helper_check_state(state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); +} + +/* Takes a fixed 16.16 number and converts it to integer. */ +static inline int64_t fixed16_to_int(int64_t value) +{ + return value >> 16; +} + +static void meson_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct meson_plane *meson_plane = to_meson_plane(plane); + struct drm_plane_state *state = plane->state; + struct drm_framebuffer *fb = state->fb; + struct meson_drm *priv = meson_plane->priv; + struct drm_gem_cma_object *gem; + struct drm_rect src = { + .x1 = (state->src_x), + .y1 = (state->src_y), + .x2 = (state->src_x + state->src_w), + .y2 = (state->src_y + state->src_h), + }; + struct drm_rect dest = { + .x1 = state->crtc_x, + .y1 = state->crtc_y, + .x2 = state->crtc_x + state->crtc_w, + .y2 = state->crtc_y + state->crtc_h, + }; + unsigned long flags; + + /* + * Update Coordinates + * Update Formats + * Update Buffer + * Enable Plane + */ + spin_lock_irqsave(&priv->drm->event_lock, flags); + + /* Enable OSD and BLK0, set max global alpha */ + priv->viu.osd1_ctrl_stat = OSD_ENABLE | + (0xFF << OSD_GLOBAL_ALPHA_SHIFT) | + OSD_BLK0_ENABLE; + + /* Set up BLK0 to point to the right canvas */ + priv->viu.osd1_blk0_cfg[0] = ((MESON_CANVAS_ID_OSD1 << OSD_CANVAS_SEL) | + OSD_ENDIANNESS_LE); + + /* On GXBB, Use the old non-HDR RGB2YUV converter */ + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) + priv->viu.osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB; + + switch (fb->pixel_format) { + case DRM_FORMAT_XRGB8888: + /* For XRGB, replace the pixel's alpha by 0xFF */ + writel_bits_relaxed(OSD_REPLACE_EN, OSD_REPLACE_EN, + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); + priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 | + OSD_COLOR_MATRIX_32_ARGB; + break; + case DRM_FORMAT_ARGB8888: + /* For ARGB, use the pixel's alpha */ + writel_bits_relaxed(OSD_REPLACE_EN, 0, + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); + priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 | + OSD_COLOR_MATRIX_32_ARGB; + break; + case DRM_FORMAT_RGB888: + priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_24 | + OSD_COLOR_MATRIX_24_RGB; + break; + case DRM_FORMAT_RGB565: + priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_16 | + OSD_COLOR_MATRIX_16_RGB565; + break; + }; + + if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) { + priv->viu.osd1_interlace = true; + + dest.y1 /= 2; + dest.y2 /= 2; + } else + priv->viu.osd1_interlace = false; + + /* + * The format of these registers is (x2 << 16 | x1), + * where x2 is exclusive. + * e.g. +30x1920 would be (1919 << 16) | 30 + */ + priv->viu.osd1_blk0_cfg[1] = ((fixed16_to_int(src.x2) - 1) << 16) | + fixed16_to_int(src.x1); + priv->viu.osd1_blk0_cfg[2] = ((fixed16_to_int(src.y2) - 1) << 16) | + fixed16_to_int(src.y1); + priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1; + priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1; + + /* Update Canvas with buffer address */ + gem = drm_fb_cma_get_gem_obj(fb, 0); + + meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1, + gem->paddr, fb->pitches[0], + fb->height, MESON_CANVAS_WRAP_NONE, + MESON_CANVAS_BLKMODE_LINEAR); + + spin_unlock_irqrestore(&priv->drm->event_lock, flags); +} + +static void meson_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct meson_plane *meson_plane = to_meson_plane(plane); + struct meson_drm *priv = meson_plane->priv; + + /* Disable OSD1 */ + writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0, + priv->io_base + _REG(VPP_MISC)); + +} + +static const struct drm_plane_helper_funcs meson_plane_helper_funcs = { + .atomic_check = meson_plane_atomic_check, + .atomic_disable = meson_plane_atomic_disable, + .atomic_update = meson_plane_atomic_update, +}; + +static const struct drm_plane_funcs meson_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const uint32_t supported_drm_formats[] = { + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, +}; + +int meson_plane_create(struct meson_drm *priv) +{ + struct meson_plane *meson_plane; + struct drm_plane *plane; + + meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane), + GFP_KERNEL); + if (!meson_plane) + return -ENOMEM; + + meson_plane->priv = priv; + plane = &meson_plane->base; + + drm_universal_plane_init(priv->drm, plane, 0xFF, + &meson_plane_funcs, + supported_drm_formats, + ARRAY_SIZE(supported_drm_formats), + DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane"); + + drm_plane_helper_add(plane, &meson_plane_helper_funcs); + + priv->primary_plane = plane; + + return 0; +} diff --git a/drivers/gpu/drm/meson/meson_plane.h b/drivers/gpu/drm/meson/meson_plane.h new file mode 100644 index 000000000000..e26b8b0aa1fa --- /dev/null +++ b/drivers/gpu/drm/meson/meson_plane.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Written by: + * Jasper St. Pierre + */ + +#ifndef __MESON_PLANE_H +#define __MESON_PLANE_H + +#include "meson_drv.h" + +int meson_plane_create(struct meson_drm *priv); + +#endif /* __MESON_PLANE_H */ diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h new file mode 100644 index 000000000000..6adf9c13fafa --- /dev/null +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -0,0 +1,1395 @@ +/* + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef __MESON_REGISTERS_H +#define __MESON_REGISTERS_H + +/* Shift all registers by 2 */ +#define _REG(reg) ((reg) << 2) + +#define writel_bits_relaxed(mask, val, addr) \ + writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr) + +/* vpp2 */ +#define VPP2_DUMMY_DATA 0x1900 +#define VPP2_LINE_IN_LENGTH 0x1901 +#define VPP2_PIC_IN_HEIGHT 0x1902 +#define VPP2_SCALE_COEF_IDX 0x1903 +#define VPP2_SCALE_COEF 0x1904 +#define VPP2_VSC_REGION12_STARTP 0x1905 +#define VPP2_VSC_REGION34_STARTP 0x1906 +#define VPP2_VSC_REGION4_ENDP 0x1907 +#define VPP2_VSC_START_PHASE_STEP 0x1908 +#define VPP2_VSC_REGION0_PHASE_SLOPE 0x1909 +#define VPP2_VSC_REGION1_PHASE_SLOPE 0x190a +#define VPP2_VSC_REGION3_PHASE_SLOPE 0x190b +#define VPP2_VSC_REGION4_PHASE_SLOPE 0x190c +#define VPP2_VSC_PHASE_CTRL 0x190d +#define VPP2_VSC_INI_PHASE 0x190e +#define VPP2_HSC_REGION12_STARTP 0x1910 +#define VPP2_HSC_REGION34_STARTP 0x1911 +#define VPP2_HSC_REGION4_ENDP 0x1912 +#define VPP2_HSC_START_PHASE_STEP 0x1913 +#define VPP2_HSC_REGION0_PHASE_SLOPE 0x1914 +#define VPP2_HSC_REGION1_PHASE_SLOPE 0x1915 +#define VPP2_HSC_REGION3_PHASE_SLOPE 0x1916 +#define VPP2_HSC_REGION4_PHASE_SLOPE 0x1917 +#define VPP2_HSC_PHASE_CTRL 0x1918 +#define VPP2_SC_MISC 0x1919 +#define VPP2_PREBLEND_VD1_H_START_END 0x191a +#define VPP2_PREBLEND_VD1_V_START_END 0x191b +#define VPP2_POSTBLEND_VD1_H_START_END 0x191c +#define VPP2_POSTBLEND_VD1_V_START_END 0x191d +#define VPP2_PREBLEND_H_SIZE 0x1920 +#define VPP2_POSTBLEND_H_SIZE 0x1921 +#define VPP2_HOLD_LINES 0x1922 +#define VPP2_BLEND_ONECOLOR_CTRL 0x1923 +#define VPP2_PREBLEND_CURRENT_XY 0x1924 +#define VPP2_POSTBLEND_CURRENT_XY 0x1925 +#define VPP2_MISC 0x1926 +#define VPP2_OFIFO_SIZE 0x1927 +#define VPP2_FIFO_STATUS 0x1928 +#define VPP2_SMOKE_CTRL 0x1929 +#define VPP2_SMOKE1_VAL 0x192a +#define VPP2_SMOKE2_VAL 0x192b +#define VPP2_SMOKE1_H_START_END 0x192d +#define VPP2_SMOKE1_V_START_END 0x192e +#define VPP2_SMOKE2_H_START_END 0x192f +#define VPP2_SMOKE2_V_START_END 0x1930 +#define VPP2_SCO_FIFO_CTRL 0x1933 +#define VPP2_HSC_PHASE_CTRL1 0x1934 +#define VPP2_HSC_INI_PAT_CTRL 0x1935 +#define VPP2_VADJ_CTRL 0x1940 +#define VPP2_VADJ1_Y 0x1941 +#define VPP2_VADJ1_MA_MB 0x1942 +#define VPP2_VADJ1_MC_MD 0x1943 +#define VPP2_VADJ2_Y 0x1944 +#define VPP2_VADJ2_MA_MB 0x1945 +#define VPP2_VADJ2_MC_MD 0x1946 +#define VPP2_MATRIX_PROBE_COLOR 0x195c +#define VPP2_MATRIX_HL_COLOR 0x195d +#define VPP2_MATRIX_PROBE_POS 0x195e +#define VPP2_MATRIX_CTRL 0x195f +#define VPP2_MATRIX_COEF00_01 0x1960 +#define VPP2_MATRIX_COEF02_10 0x1961 +#define VPP2_MATRIX_COEF11_12 0x1962 +#define VPP2_MATRIX_COEF20_21 0x1963 +#define VPP2_MATRIX_COEF22 0x1964 +#define VPP2_MATRIX_OFFSET0_1 0x1965 +#define VPP2_MATRIX_OFFSET2 0x1966 +#define VPP2_MATRIX_PRE_OFFSET0_1 0x1967 +#define VPP2_MATRIX_PRE_OFFSET2 0x1968 +#define VPP2_DUMMY_DATA1 0x1969 +#define VPP2_GAINOFF_CTRL0 0x196a +#define VPP2_GAINOFF_CTRL1 0x196b +#define VPP2_GAINOFF_CTRL2 0x196c +#define VPP2_GAINOFF_CTRL3 0x196d +#define VPP2_GAINOFF_CTRL4 0x196e +#define VPP2_CHROMA_ADDR_PORT 0x1970 +#define VPP2_CHROMA_DATA_PORT 0x1971 +#define VPP2_GCLK_CTRL0 0x1972 +#define VPP2_GCLK_CTRL1 0x1973 +#define VPP2_SC_GCLK_CTRL 0x1974 +#define VPP2_MISC1 0x1976 +#define VPP2_DNLP_CTRL_00 0x1981 +#define VPP2_DNLP_CTRL_01 0x1982 +#define VPP2_DNLP_CTRL_02 0x1983 +#define VPP2_DNLP_CTRL_03 0x1984 +#define VPP2_DNLP_CTRL_04 0x1985 +#define VPP2_DNLP_CTRL_05 0x1986 +#define VPP2_DNLP_CTRL_06 0x1987 +#define VPP2_DNLP_CTRL_07 0x1988 +#define VPP2_DNLP_CTRL_08 0x1989 +#define VPP2_DNLP_CTRL_09 0x198a +#define VPP2_DNLP_CTRL_10 0x198b +#define VPP2_DNLP_CTRL_11 0x198c +#define VPP2_DNLP_CTRL_12 0x198d +#define VPP2_DNLP_CTRL_13 0x198e +#define VPP2_DNLP_CTRL_14 0x198f +#define VPP2_DNLP_CTRL_15 0x1990 +#define VPP2_VE_ENABLE_CTRL 0x19a1 +#define VPP2_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x19a2 +#define VPP2_VE_DEMO_CENTER_BAR 0x19a3 +#define VPP2_VE_H_V_SIZE 0x19a4 +#define VPP2_VDO_MEAS_CTRL 0x19a8 +#define VPP2_VDO_MEAS_VS_COUNT_HI 0x19a9 +#define VPP2_VDO_MEAS_VS_COUNT_LO 0x19aa +#define VPP2_OSD_VSC_PHASE_STEP 0x19c0 +#define VPP2_OSD_VSC_INI_PHASE 0x19c1 +#define VPP2_OSD_VSC_CTRL0 0x19c2 +#define VPP2_OSD_HSC_PHASE_STEP 0x19c3 +#define VPP2_OSD_HSC_INI_PHASE 0x19c4 +#define VPP2_OSD_HSC_CTRL0 0x19c5 +#define VPP2_OSD_HSC_INI_PAT_CTRL 0x19c6 +#define VPP2_OSD_SC_DUMMY_DATA 0x19c7 +#define VPP2_OSD_SC_CTRL0 0x19c8 +#define VPP2_OSD_SCI_WH_M1 0x19c9 +#define VPP2_OSD_SCO_H_START_END 0x19ca +#define VPP2_OSD_SCO_V_START_END 0x19cb +#define VPP2_OSD_SCALE_COEF_IDX 0x19cc +#define VPP2_OSD_SCALE_COEF 0x19cd +#define VPP2_INT_LINE_NUM 0x19ce + +/* viu */ +#define VIU_ADDR_START 0x1a00 +#define VIU_ADDR_END 0x1aff +#define VIU_SW_RESET 0x1a01 +#define VIU_MISC_CTRL0 0x1a06 +#define VIU_MISC_CTRL1 0x1a07 +#define D2D3_INTF_LENGTH 0x1a08 +#define D2D3_INTF_CTRL0 0x1a09 +#define VIU_OSD1_CTRL_STAT 0x1a10 +#define VIU_OSD1_CTRL_STAT2 0x1a2d +#define VIU_OSD1_COLOR_ADDR 0x1a11 +#define VIU_OSD1_COLOR 0x1a12 +#define VIU_OSD1_TCOLOR_AG0 0x1a17 +#define VIU_OSD1_TCOLOR_AG1 0x1a18 +#define VIU_OSD1_TCOLOR_AG2 0x1a19 +#define VIU_OSD1_TCOLOR_AG3 0x1a1a +#define VIU_OSD1_BLK0_CFG_W0 0x1a1b +#define VIU_OSD1_BLK1_CFG_W0 0x1a1f +#define VIU_OSD1_BLK2_CFG_W0 0x1a23 +#define VIU_OSD1_BLK3_CFG_W0 0x1a27 +#define VIU_OSD1_BLK0_CFG_W1 0x1a1c +#define VIU_OSD1_BLK1_CFG_W1 0x1a20 +#define VIU_OSD1_BLK2_CFG_W1 0x1a24 +#define VIU_OSD1_BLK3_CFG_W1 0x1a28 +#define VIU_OSD1_BLK0_CFG_W2 0x1a1d +#define VIU_OSD1_BLK1_CFG_W2 0x1a21 +#define VIU_OSD1_BLK2_CFG_W2 0x1a25 +#define VIU_OSD1_BLK3_CFG_W2 0x1a29 +#define VIU_OSD1_BLK0_CFG_W3 0x1a1e +#define VIU_OSD1_BLK1_CFG_W3 0x1a22 +#define VIU_OSD1_BLK2_CFG_W3 0x1a26 +#define VIU_OSD1_BLK3_CFG_W3 0x1a2a +#define VIU_OSD1_BLK0_CFG_W4 0x1a13 +#define VIU_OSD1_BLK1_CFG_W4 0x1a14 +#define VIU_OSD1_BLK2_CFG_W4 0x1a15 +#define VIU_OSD1_BLK3_CFG_W4 0x1a16 +#define VIU_OSD1_FIFO_CTRL_STAT 0x1a2b +#define VIU_OSD1_TEST_RDDATA 0x1a2c +#define VIU_OSD1_PROT_CTRL 0x1a2e +#define VIU_OSD2_CTRL_STAT 0x1a30 +#define VIU_OSD2_CTRL_STAT2 0x1a4d +#define VIU_OSD2_COLOR_ADDR 0x1a31 +#define VIU_OSD2_COLOR 0x1a32 +#define VIU_OSD2_HL1_H_START_END 0x1a33 +#define VIU_OSD2_HL1_V_START_END 0x1a34 +#define VIU_OSD2_HL2_H_START_END 0x1a35 +#define VIU_OSD2_HL2_V_START_END 0x1a36 +#define VIU_OSD2_TCOLOR_AG0 0x1a37 +#define VIU_OSD2_TCOLOR_AG1 0x1a38 +#define VIU_OSD2_TCOLOR_AG2 0x1a39 +#define VIU_OSD2_TCOLOR_AG3 0x1a3a +#define VIU_OSD2_BLK0_CFG_W0 0x1a3b +#define VIU_OSD2_BLK1_CFG_W0 0x1a3f +#define VIU_OSD2_BLK2_CFG_W0 0x1a43 +#define VIU_OSD2_BLK3_CFG_W0 0x1a47 +#define VIU_OSD2_BLK0_CFG_W1 0x1a3c +#define VIU_OSD2_BLK1_CFG_W1 0x1a40 +#define VIU_OSD2_BLK2_CFG_W1 0x1a44 +#define VIU_OSD2_BLK3_CFG_W1 0x1a48 +#define VIU_OSD2_BLK0_CFG_W2 0x1a3d +#define VIU_OSD2_BLK1_CFG_W2 0x1a41 +#define VIU_OSD2_BLK2_CFG_W2 0x1a45 +#define VIU_OSD2_BLK3_CFG_W2 0x1a49 +#define VIU_OSD2_BLK0_CFG_W3 0x1a3e +#define VIU_OSD2_BLK1_CFG_W3 0x1a42 +#define VIU_OSD2_BLK2_CFG_W3 0x1a46 +#define VIU_OSD2_BLK3_CFG_W3 0x1a4a +#define VIU_OSD2_BLK0_CFG_W4 0x1a64 +#define VIU_OSD2_BLK1_CFG_W4 0x1a65 +#define VIU_OSD2_BLK2_CFG_W4 0x1a66 +#define VIU_OSD2_BLK3_CFG_W4 0x1a67 +#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b +#define VIU_OSD2_TEST_RDDATA 0x1a4c +#define VIU_OSD2_PROT_CTRL 0x1a4e + +#define VD1_IF0_GEN_REG 0x1a50 +#define VD1_IF0_CANVAS0 0x1a51 +#define VD1_IF0_CANVAS1 0x1a52 +#define VD1_IF0_LUMA_X0 0x1a53 +#define VD1_IF0_LUMA_Y0 0x1a54 +#define VD1_IF0_CHROMA_X0 0x1a55 +#define VD1_IF0_CHROMA_Y0 0x1a56 +#define VD1_IF0_LUMA_X1 0x1a57 +#define VD1_IF0_LUMA_Y1 0x1a58 +#define VD1_IF0_CHROMA_X1 0x1a59 +#define VD1_IF0_CHROMA_Y1 0x1a5a +#define VD1_IF0_RPT_LOOP 0x1a5b +#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c +#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d +#define VD1_IF0_LUMA1_RPT_PAT 0x1a5e +#define VD1_IF0_CHROMA1_RPT_PAT 0x1a5f +#define VD1_IF0_LUMA_PSEL 0x1a60 +#define VD1_IF0_CHROMA_PSEL 0x1a61 +#define VD1_IF0_DUMMY_PIXEL 0x1a62 +#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63 +#define VD1_IF0_RANGE_MAP_Y 0x1a6a +#define VD1_IF0_RANGE_MAP_CB 0x1a6b +#define VD1_IF0_RANGE_MAP_CR 0x1a6c +#define VD1_IF0_GEN_REG2 0x1a6d +#define VD1_IF0_PROT_CNTL 0x1a6e +#define VIU_VD1_FMT_CTRL 0x1a68 +#define VIU_VD1_FMT_W 0x1a69 +#define VD2_IF0_GEN_REG 0x1a70 +#define VD2_IF0_CANVAS0 0x1a71 +#define VD2_IF0_CANVAS1 0x1a72 +#define VD2_IF0_LUMA_X0 0x1a73 +#define VD2_IF0_LUMA_Y0 0x1a74 +#define VD2_IF0_CHROMA_X0 0x1a75 +#define VD2_IF0_CHROMA_Y0 0x1a76 +#define VD2_IF0_LUMA_X1 0x1a77 +#define VD2_IF0_LUMA_Y1 0x1a78 +#define VD2_IF0_CHROMA_X1 0x1a79 +#define VD2_IF0_CHROMA_Y1 0x1a7a +#define VD2_IF0_RPT_LOOP 0x1a7b +#define VD2_IF0_LUMA0_RPT_PAT 0x1a7c +#define VD2_IF0_CHROMA0_RPT_PAT 0x1a7d +#define VD2_IF0_LUMA1_RPT_PAT 0x1a7e +#define VD2_IF0_CHROMA1_RPT_PAT 0x1a7f +#define VD2_IF0_LUMA_PSEL 0x1a80 +#define VD2_IF0_CHROMA_PSEL 0x1a81 +#define VD2_IF0_DUMMY_PIXEL 0x1a82 +#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83 +#define VD2_IF0_RANGE_MAP_Y 0x1a8a +#define VD2_IF0_RANGE_MAP_CB 0x1a8b +#define VD2_IF0_RANGE_MAP_CR 0x1a8c +#define VD2_IF0_GEN_REG2 0x1a8d +#define VD2_IF0_PROT_CNTL 0x1a8e +#define VIU_VD2_FMT_CTRL 0x1a88 +#define VIU_VD2_FMT_W 0x1a89 + +/* VIU Matrix Registers */ +#define VIU_OSD1_MATRIX_CTRL 0x1a90 +#define VIU_OSD1_MATRIX_COEF00_01 0x1a91 +#define VIU_OSD1_MATRIX_COEF02_10 0x1a92 +#define VIU_OSD1_MATRIX_COEF11_12 0x1a93 +#define VIU_OSD1_MATRIX_COEF20_21 0x1a94 +#define VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95 +#define VIU_OSD1_MATRIX_OFFSET0_1 0x1a96 +#define VIU_OSD1_MATRIX_OFFSET2 0x1a97 +#define VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98 +#define VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99 +#define VIU_OSD1_MATRIX_COEF22_30 0x1a9d +#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e +#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f +#define VIU_OSD1_EOTF_CTL 0x1ad4 +#define VIU_OSD1_EOTF_COEF00_01 0x1ad5 +#define VIU_OSD1_EOTF_COEF02_10 0x1ad6 +#define VIU_OSD1_EOTF_COEF11_12 0x1ad7 +#define VIU_OSD1_EOTF_COEF20_21 0x1ad8 +#define VIU_OSD1_EOTF_COEF22_RS 0x1ad9 +#define VIU_OSD1_EOTF_LUT_ADDR_PORT 0x1ada +#define VIU_OSD1_EOTF_LUT_DATA_PORT 0x1adb +#define VIU_OSD1_OETF_CTL 0x1adc +#define VIU_OSD1_OETF_LUT_ADDR_PORT 0x1add +#define VIU_OSD1_OETF_LUT_DATA_PORT 0x1ade + +/* vpp */ +#define VPP_DUMMY_DATA 0x1d00 +#define VPP_LINE_IN_LENGTH 0x1d01 +#define VPP_PIC_IN_HEIGHT 0x1d02 +#define VPP_SCALE_COEF_IDX 0x1d03 +#define VPP_SCALE_COEF 0x1d04 +#define VPP_VSC_REGION12_STARTP 0x1d05 +#define VPP_VSC_REGION34_STARTP 0x1d06 +#define VPP_VSC_REGION4_ENDP 0x1d07 +#define VPP_VSC_START_PHASE_STEP 0x1d08 +#define VPP_VSC_REGION0_PHASE_SLOPE 0x1d09 +#define VPP_VSC_REGION1_PHASE_SLOPE 0x1d0a +#define VPP_VSC_REGION3_PHASE_SLOPE 0x1d0b +#define VPP_VSC_REGION4_PHASE_SLOPE 0x1d0c +#define VPP_VSC_PHASE_CTRL 0x1d0d +#define VPP_VSC_INI_PHASE 0x1d0e +#define VPP_HSC_REGION12_STARTP 0x1d10 +#define VPP_HSC_REGION34_STARTP 0x1d11 +#define VPP_HSC_REGION4_ENDP 0x1d12 +#define VPP_HSC_START_PHASE_STEP 0x1d13 +#define VPP_HSC_REGION0_PHASE_SLOPE 0x1d14 +#define VPP_HSC_REGION1_PHASE_SLOPE 0x1d15 +#define VPP_HSC_REGION3_PHASE_SLOPE 0x1d16 +#define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17 +#define VPP_HSC_PHASE_CTRL 0x1d18 +#define VPP_SC_MISC 0x1d19 +#define VPP_PREBLEND_VD1_H_START_END 0x1d1a +#define VPP_PREBLEND_VD1_V_START_END 0x1d1b +#define VPP_POSTBLEND_VD1_H_START_END 0x1d1c +#define VPP_POSTBLEND_VD1_V_START_END 0x1d1d +#define VPP_BLEND_VD2_H_START_END 0x1d1e +#define VPP_BLEND_VD2_V_START_END 0x1d1f +#define VPP_PREBLEND_H_SIZE 0x1d20 +#define VPP_POSTBLEND_H_SIZE 0x1d21 +#define VPP_HOLD_LINES 0x1d22 +#define VPP_BLEND_ONECOLOR_CTRL 0x1d23 +#define VPP_PREBLEND_CURRENT_XY 0x1d24 +#define VPP_POSTBLEND_CURRENT_XY 0x1d25 +#define VPP_MISC 0x1d26 +#define VPP_PREBLEND_ENABLE BIT(6) +#define VPP_POSTBLEND_ENABLE BIT(7) +#define VPP_OSD2_ALPHA_PREMULT BIT(8) +#define VPP_OSD1_ALPHA_PREMULT BIT(9) +#define VPP_VD1_POSTBLEND BIT(10) +#define VPP_VD2_POSTBLEND BIT(11) +#define VPP_OSD1_POSTBLEND BIT(12) +#define VPP_OSD2_POSTBLEND BIT(13) +#define VPP_VD1_PREBLEND BIT(14) +#define VPP_VD2_PREBLEND BIT(15) +#define VPP_OSD1_PREBLEND BIT(16) +#define VPP_OSD2_PREBLEND BIT(17) +#define VPP_OFIFO_SIZE 0x1d27 +#define VPP_FIFO_STATUS 0x1d28 +#define VPP_SMOKE_CTRL 0x1d29 +#define VPP_SMOKE1_VAL 0x1d2a +#define VPP_SMOKE2_VAL 0x1d2b +#define VPP_SMOKE3_VAL 0x1d2c +#define VPP_SMOKE1_H_START_END 0x1d2d +#define VPP_SMOKE1_V_START_END 0x1d2e +#define VPP_SMOKE2_H_START_END 0x1d2f +#define VPP_SMOKE2_V_START_END 0x1d30 +#define VPP_SMOKE3_H_START_END 0x1d31 +#define VPP_SMOKE3_V_START_END 0x1d32 +#define VPP_SCO_FIFO_CTRL 0x1d33 +#define VPP_HSC_PHASE_CTRL1 0x1d34 +#define VPP_HSC_INI_PAT_CTRL 0x1d35 +#define VPP_VADJ_CTRL 0x1d40 +#define VPP_VADJ1_Y 0x1d41 +#define VPP_VADJ1_MA_MB 0x1d42 +#define VPP_VADJ1_MC_MD 0x1d43 +#define VPP_VADJ2_Y 0x1d44 +#define VPP_VADJ2_MA_MB 0x1d45 +#define VPP_VADJ2_MC_MD 0x1d46 +#define VPP_HSHARP_CTRL 0x1d50 +#define VPP_HSHARP_LUMA_THRESH01 0x1d51 +#define VPP_HSHARP_LUMA_THRESH23 0x1d52 +#define VPP_HSHARP_CHROMA_THRESH01 0x1d53 +#define VPP_HSHARP_CHROMA_THRESH23 0x1d54 +#define VPP_HSHARP_LUMA_GAIN 0x1d55 +#define VPP_HSHARP_CHROMA_GAIN 0x1d56 +#define VPP_MATRIX_PROBE_COLOR 0x1d5c +#define VPP_MATRIX_HL_COLOR 0x1d5d +#define VPP_MATRIX_PROBE_POS 0x1d5e +#define VPP_MATRIX_CTRL 0x1d5f +#define VPP_MATRIX_COEF00_01 0x1d60 +#define VPP_MATRIX_COEF02_10 0x1d61 +#define VPP_MATRIX_COEF11_12 0x1d62 +#define VPP_MATRIX_COEF20_21 0x1d63 +#define VPP_MATRIX_COEF22 0x1d64 +#define VPP_MATRIX_OFFSET0_1 0x1d65 +#define VPP_MATRIX_OFFSET2 0x1d66 +#define VPP_MATRIX_PRE_OFFSET0_1 0x1d67 +#define VPP_MATRIX_PRE_OFFSET2 0x1d68 +#define VPP_DUMMY_DATA1 0x1d69 +#define VPP_GAINOFF_CTRL0 0x1d6a +#define VPP_GAINOFF_CTRL1 0x1d6b +#define VPP_GAINOFF_CTRL2 0x1d6c +#define VPP_GAINOFF_CTRL3 0x1d6d +#define VPP_GAINOFF_CTRL4 0x1d6e +#define VPP_CHROMA_ADDR_PORT 0x1d70 +#define VPP_CHROMA_DATA_PORT 0x1d71 +#define VPP_GCLK_CTRL0 0x1d72 +#define VPP_GCLK_CTRL1 0x1d73 +#define VPP_SC_GCLK_CTRL 0x1d74 +#define VPP_MISC1 0x1d76 +#define VPP_BLACKEXT_CTRL 0x1d80 +#define VPP_DNLP_CTRL_00 0x1d81 +#define VPP_DNLP_CTRL_01 0x1d82 +#define VPP_DNLP_CTRL_02 0x1d83 +#define VPP_DNLP_CTRL_03 0x1d84 +#define VPP_DNLP_CTRL_04 0x1d85 +#define VPP_DNLP_CTRL_05 0x1d86 +#define VPP_DNLP_CTRL_06 0x1d87 +#define VPP_DNLP_CTRL_07 0x1d88 +#define VPP_DNLP_CTRL_08 0x1d89 +#define VPP_DNLP_CTRL_09 0x1d8a +#define VPP_DNLP_CTRL_10 0x1d8b +#define VPP_DNLP_CTRL_11 0x1d8c +#define VPP_DNLP_CTRL_12 0x1d8d +#define VPP_DNLP_CTRL_13 0x1d8e +#define VPP_DNLP_CTRL_14 0x1d8f +#define VPP_DNLP_CTRL_15 0x1d90 +#define VPP_PEAKING_HGAIN 0x1d91 +#define VPP_PEAKING_VGAIN 0x1d92 +#define VPP_PEAKING_NLP_1 0x1d93 +#define VPP_DOLBY_CTRL 0x1d93 +#define VPP_PEAKING_NLP_2 0x1d94 +#define VPP_PEAKING_NLP_3 0x1d95 +#define VPP_PEAKING_NLP_4 0x1d96 +#define VPP_PEAKING_NLP_5 0x1d97 +#define VPP_SHARP_LIMIT 0x1d98 +#define VPP_VLTI_CTRL 0x1d99 +#define VPP_HLTI_CTRL 0x1d9a +#define VPP_CTI_CTRL 0x1d9b +#define VPP_BLUE_STRETCH_1 0x1d9c +#define VPP_BLUE_STRETCH_2 0x1d9d +#define VPP_BLUE_STRETCH_3 0x1d9e +#define VPP_CCORING_CTRL 0x1da0 +#define VPP_VE_ENABLE_CTRL 0x1da1 +#define VPP_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x1da2 +#define VPP_VE_DEMO_CENTER_BAR 0x1da3 +#define VPP_VE_H_V_SIZE 0x1da4 +#define VPP_VDO_MEAS_CTRL 0x1da8 +#define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9 +#define VPP_VDO_MEAS_VS_COUNT_LO 0x1daa +#define VPP_INPUT_CTRL 0x1dab +#define VPP_CTI_CTRL2 0x1dac +#define VPP_PEAKING_SAT_THD1 0x1dad +#define VPP_PEAKING_SAT_THD2 0x1dae +#define VPP_PEAKING_SAT_THD3 0x1daf +#define VPP_PEAKING_SAT_THD4 0x1db0 +#define VPP_PEAKING_SAT_THD5 0x1db1 +#define VPP_PEAKING_SAT_THD6 0x1db2 +#define VPP_PEAKING_SAT_THD7 0x1db3 +#define VPP_PEAKING_SAT_THD8 0x1db4 +#define VPP_PEAKING_SAT_THD9 0x1db5 +#define VPP_PEAKING_GAIN_ADD1 0x1db6 +#define VPP_PEAKING_GAIN_ADD2 0x1db7 +#define VPP_PEAKING_DNLP 0x1db8 +#define VPP_SHARP_DEMO_WIN_CTRL1 0x1db9 +#define VPP_SHARP_DEMO_WIN_CTRL2 0x1dba +#define VPP_FRONT_HLTI_CTRL 0x1dbb +#define VPP_FRONT_CTI_CTRL 0x1dbc +#define VPP_FRONT_CTI_CTRL2 0x1dbd +#define VPP_OSD_VSC_PHASE_STEP 0x1dc0 +#define VPP_OSD_VSC_INI_PHASE 0x1dc1 +#define VPP_OSD_VSC_CTRL0 0x1dc2 +#define VPP_OSD_HSC_PHASE_STEP 0x1dc3 +#define VPP_OSD_HSC_INI_PHASE 0x1dc4 +#define VPP_OSD_HSC_CTRL0 0x1dc5 +#define VPP_OSD_HSC_INI_PAT_CTRL 0x1dc6 +#define VPP_OSD_SC_DUMMY_DATA 0x1dc7 +#define VPP_OSD_SC_CTRL0 0x1dc8 +#define VPP_OSD_SCI_WH_M1 0x1dc9 +#define VPP_OSD_SCO_H_START_END 0x1dca +#define VPP_OSD_SCO_V_START_END 0x1dcb +#define VPP_OSD_SCALE_COEF_IDX 0x1dcc +#define VPP_OSD_SCALE_COEF 0x1dcd +#define VPP_INT_LINE_NUM 0x1dce + +/* viu2 */ +#define VIU2_ADDR_START 0x1e00 +#define VIU2_ADDR_END 0x1eff +#define VIU2_SW_RESET 0x1e01 +#define VIU2_OSD1_CTRL_STAT 0x1e10 +#define VIU2_OSD1_CTRL_STAT2 0x1e2d +#define VIU2_OSD1_COLOR_ADDR 0x1e11 +#define VIU2_OSD1_COLOR 0x1e12 +#define VIU2_OSD1_TCOLOR_AG0 0x1e17 +#define VIU2_OSD1_TCOLOR_AG1 0x1e18 +#define VIU2_OSD1_TCOLOR_AG2 0x1e19 +#define VIU2_OSD1_TCOLOR_AG3 0x1e1a +#define VIU2_OSD1_BLK0_CFG_W0 0x1e1b +#define VIU2_OSD1_BLK1_CFG_W0 0x1e1f +#define VIU2_OSD1_BLK2_CFG_W0 0x1e23 +#define VIU2_OSD1_BLK3_CFG_W0 0x1e27 +#define VIU2_OSD1_BLK0_CFG_W1 0x1e1c +#define VIU2_OSD1_BLK1_CFG_W1 0x1e20 +#define VIU2_OSD1_BLK2_CFG_W1 0x1e24 +#define VIU2_OSD1_BLK3_CFG_W1 0x1e28 +#define VIU2_OSD1_BLK0_CFG_W2 0x1e1d +#define VIU2_OSD1_BLK1_CFG_W2 0x1e21 +#define VIU2_OSD1_BLK2_CFG_W2 0x1e25 +#define VIU2_OSD1_BLK3_CFG_W2 0x1e29 +#define VIU2_OSD1_BLK0_CFG_W3 0x1e1e +#define VIU2_OSD1_BLK1_CFG_W3 0x1e22 +#define VIU2_OSD1_BLK2_CFG_W3 0x1e26 +#define VIU2_OSD1_BLK3_CFG_W3 0x1e2a +#define VIU2_OSD1_BLK0_CFG_W4 0x1e13 +#define VIU2_OSD1_BLK1_CFG_W4 0x1e14 +#define VIU2_OSD1_BLK2_CFG_W4 0x1e15 +#define VIU2_OSD1_BLK3_CFG_W4 0x1e16 +#define VIU2_OSD1_FIFO_CTRL_STAT 0x1e2b +#define VIU2_OSD1_TEST_RDDATA 0x1e2c +#define VIU2_OSD1_PROT_CTRL 0x1e2e +#define VIU2_OSD2_CTRL_STAT 0x1e30 +#define VIU2_OSD2_CTRL_STAT2 0x1e4d +#define VIU2_OSD2_COLOR_ADDR 0x1e31 +#define VIU2_OSD2_COLOR 0x1e32 +#define VIU2_OSD2_HL1_H_START_END 0x1e33 +#define VIU2_OSD2_HL1_V_START_END 0x1e34 +#define VIU2_OSD2_HL2_H_START_END 0x1e35 +#define VIU2_OSD2_HL2_V_START_END 0x1e36 +#define VIU2_OSD2_TCOLOR_AG0 0x1e37 +#define VIU2_OSD2_TCOLOR_AG1 0x1e38 +#define VIU2_OSD2_TCOLOR_AG2 0x1e39 +#define VIU2_OSD2_TCOLOR_AG3 0x1e3a +#define VIU2_OSD2_BLK0_CFG_W0 0x1e3b +#define VIU2_OSD2_BLK1_CFG_W0 0x1e3f +#define VIU2_OSD2_BLK2_CFG_W0 0x1e43 +#define VIU2_OSD2_BLK3_CFG_W0 0x1e47 +#define VIU2_OSD2_BLK0_CFG_W1 0x1e3c +#define VIU2_OSD2_BLK1_CFG_W1 0x1e40 +#define VIU2_OSD2_BLK2_CFG_W1 0x1e44 +#define VIU2_OSD2_BLK3_CFG_W1 0x1e48 +#define VIU2_OSD2_BLK0_CFG_W2 0x1e3d +#define VIU2_OSD2_BLK1_CFG_W2 0x1e41 +#define VIU2_OSD2_BLK2_CFG_W2 0x1e45 +#define VIU2_OSD2_BLK3_CFG_W2 0x1e49 +#define VIU2_OSD2_BLK0_CFG_W3 0x1e3e +#define VIU2_OSD2_BLK1_CFG_W3 0x1e42 +#define VIU2_OSD2_BLK2_CFG_W3 0x1e46 +#define VIU2_OSD2_BLK3_CFG_W3 0x1e4a +#define VIU2_OSD2_BLK0_CFG_W4 0x1e64 +#define VIU2_OSD2_BLK1_CFG_W4 0x1e65 +#define VIU2_OSD2_BLK2_CFG_W4 0x1e66 +#define VIU2_OSD2_BLK3_CFG_W4 0x1e67 +#define VIU2_OSD2_FIFO_CTRL_STAT 0x1e4b +#define VIU2_OSD2_TEST_RDDATA 0x1e4c +#define VIU2_OSD2_PROT_CTRL 0x1e4e +#define VIU2_VD1_IF0_GEN_REG 0x1e50 +#define VIU2_VD1_IF0_CANVAS0 0x1e51 +#define VIU2_VD1_IF0_CANVAS1 0x1e52 +#define VIU2_VD1_IF0_LUMA_X0 0x1e53 +#define VIU2_VD1_IF0_LUMA_Y0 0x1e54 +#define VIU2_VD1_IF0_CHROMA_X0 0x1e55 +#define VIU2_VD1_IF0_CHROMA_Y0 0x1e56 +#define VIU2_VD1_IF0_LUMA_X1 0x1e57 +#define VIU2_VD1_IF0_LUMA_Y1 0x1e58 +#define VIU2_VD1_IF0_CHROMA_X1 0x1e59 +#define VIU2_VD1_IF0_CHROMA_Y1 0x1e5a +#define VIU2_VD1_IF0_RPT_LOOP 0x1e5b +#define VIU2_VD1_IF0_LUMA0_RPT_PAT 0x1e5c +#define VIU2_VD1_IF0_CHROMA0_RPT_PAT 0x1e5d +#define VIU2_VD1_IF0_LUMA1_RPT_PAT 0x1e5e +#define VIU2_VD1_IF0_CHROMA1_RPT_PAT 0x1e5f +#define VIU2_VD1_IF0_LUMA_PSEL 0x1e60 +#define VIU2_VD1_IF0_CHROMA_PSEL 0x1e61 +#define VIU2_VD1_IF0_DUMMY_PIXEL 0x1e62 +#define VIU2_VD1_IF0_LUMA_FIFO_SIZE 0x1e63 +#define VIU2_VD1_IF0_RANGE_MAP_Y 0x1e6a +#define VIU2_VD1_IF0_RANGE_MAP_CB 0x1e6b +#define VIU2_VD1_IF0_RANGE_MAP_CR 0x1e6c +#define VIU2_VD1_IF0_GEN_REG2 0x1e6d +#define VIU2_VD1_IF0_PROT_CNTL 0x1e6e +#define VIU2_VD1_FMT_CTRL 0x1e68 +#define VIU2_VD1_FMT_W 0x1e69 + +/* encode */ +#define ENCP_VFIFO2VD_CTL 0x1b58 +#define ENCP_VFIFO2VD_PIXEL_START 0x1b59 +#define ENCP_VFIFO2VD_PIXEL_END 0x1b5a +#define ENCP_VFIFO2VD_LINE_TOP_START 0x1b5b +#define ENCP_VFIFO2VD_LINE_TOP_END 0x1b5c +#define ENCP_VFIFO2VD_LINE_BOT_START 0x1b5d +#define ENCP_VFIFO2VD_LINE_BOT_END 0x1b5e +#define VENC_SYNC_ROUTE 0x1b60 +#define VENC_VIDEO_EXSRC 0x1b61 +#define VENC_DVI_SETTING 0x1b62 +#define VENC_C656_CTRL 0x1b63 +#define VENC_UPSAMPLE_CTRL0 0x1b64 +#define VENC_UPSAMPLE_CTRL1 0x1b65 +#define VENC_UPSAMPLE_CTRL2 0x1b66 +#define TCON_INVERT_CTL 0x1b67 +#define VENC_VIDEO_PROG_MODE 0x1b68 +#define VENC_ENCI_LINE 0x1b69 +#define VENC_ENCI_PIXEL 0x1b6a +#define VENC_ENCP_LINE 0x1b6b +#define VENC_ENCP_PIXEL 0x1b6c +#define VENC_STATA 0x1b6d +#define VENC_INTCTRL 0x1b6e +#define VENC_INTFLAG 0x1b6f +#define VENC_VIDEO_TST_EN 0x1b70 +#define VENC_VIDEO_TST_MDSEL 0x1b71 +#define VENC_VIDEO_TST_Y 0x1b72 +#define VENC_VIDEO_TST_CB 0x1b73 +#define VENC_VIDEO_TST_CR 0x1b74 +#define VENC_VIDEO_TST_CLRBAR_STRT 0x1b75 +#define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76 +#define VENC_VIDEO_TST_VDCNT_STSET 0x1b77 +#define VENC_VDAC_DACSEL0 0x1b78 +#define VENC_VDAC_DACSEL1 0x1b79 +#define VENC_VDAC_DACSEL2 0x1b7a +#define VENC_VDAC_DACSEL3 0x1b7b +#define VENC_VDAC_DACSEL4 0x1b7c +#define VENC_VDAC_DACSEL5 0x1b7d +#define VENC_VDAC_SETTING 0x1b7e +#define VENC_VDAC_TST_VAL 0x1b7f +#define VENC_VDAC_DAC0_GAINCTRL 0x1bf0 +#define VENC_VDAC_DAC0_OFFSET 0x1bf1 +#define VENC_VDAC_DAC1_GAINCTRL 0x1bf2 +#define VENC_VDAC_DAC1_OFFSET 0x1bf3 +#define VENC_VDAC_DAC2_GAINCTRL 0x1bf4 +#define VENC_VDAC_DAC2_OFFSET 0x1bf5 +#define VENC_VDAC_DAC3_GAINCTRL 0x1bf6 +#define VENC_VDAC_DAC3_OFFSET 0x1bf7 +#define VENC_VDAC_DAC4_GAINCTRL 0x1bf8 +#define VENC_VDAC_DAC4_OFFSET 0x1bf9 +#define VENC_VDAC_DAC5_GAINCTRL 0x1bfa +#define VENC_VDAC_DAC5_OFFSET 0x1bfb +#define VENC_VDAC_FIFO_CTRL 0x1bfc +#define ENCL_TCON_INVERT_CTL 0x1bfd +#define ENCP_VIDEO_EN 0x1b80 +#define ENCP_VIDEO_SYNC_MODE 0x1b81 +#define ENCP_MACV_EN 0x1b82 +#define ENCP_VIDEO_Y_SCL 0x1b83 +#define ENCP_VIDEO_PB_SCL 0x1b84 +#define ENCP_VIDEO_PR_SCL 0x1b85 +#define ENCP_VIDEO_SYNC_SCL 0x1b86 +#define ENCP_VIDEO_MACV_SCL 0x1b87 +#define ENCP_VIDEO_Y_OFFST 0x1b88 +#define ENCP_VIDEO_PB_OFFST 0x1b89 +#define ENCP_VIDEO_PR_OFFST 0x1b8a +#define ENCP_VIDEO_SYNC_OFFST 0x1b8b +#define ENCP_VIDEO_MACV_OFFST 0x1b8c +#define ENCP_VIDEO_MODE 0x1b8d +#define ENCP_VIDEO_MODE_ADV 0x1b8e +#define ENCP_DBG_PX_RST 0x1b90 +#define ENCP_DBG_LN_RST 0x1b91 +#define ENCP_DBG_PX_INT 0x1b92 +#define ENCP_DBG_LN_INT 0x1b93 +#define ENCP_VIDEO_YFP1_HTIME 0x1b94 +#define ENCP_VIDEO_YFP2_HTIME 0x1b95 +#define ENCP_VIDEO_YC_DLY 0x1b96 +#define ENCP_VIDEO_MAX_PXCNT 0x1b97 +#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98 +#define ENCP_VIDEO_HSPULS_END 0x1b99 +#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a +#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b +#define ENCP_VIDEO_VSPULS_END 0x1b9c +#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d +#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e +#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f +#define ENCP_VIDEO_EQPULS_END 0x1ba0 +#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1 +#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2 +#define ENCP_VIDEO_HAVON_END 0x1ba3 +#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4 +#define ENCP_VIDEO_VAVON_ELINE 0x1baf +#define ENCP_VIDEO_VAVON_BLINE 0x1ba6 +#define ENCP_VIDEO_HSO_BEGIN 0x1ba7 +#define ENCP_VIDEO_HSO_END 0x1ba8 +#define ENCP_VIDEO_VSO_BEGIN 0x1ba9 +#define ENCP_VIDEO_VSO_END 0x1baa +#define ENCP_VIDEO_VSO_BLINE 0x1bab +#define ENCP_VIDEO_VSO_ELINE 0x1bac +#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad +#define ENCP_VIDEO_MAX_LNCNT 0x1bae +#define ENCP_VIDEO_SY_VAL 0x1bb0 +#define ENCP_VIDEO_SY2_VAL 0x1bb1 +#define ENCP_VIDEO_BLANKY_VAL 0x1bb2 +#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3 +#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4 +#define ENCP_VIDEO_HOFFST 0x1bb5 +#define ENCP_VIDEO_VOFFST 0x1bb6 +#define ENCP_VIDEO_RGB_CTRL 0x1bb7 +#define ENCP_VIDEO_FILT_CTRL 0x1bb8 +#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9 +#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba +#define ENCP_VIDEO_MATRIX_CB 0x1bbb +#define ENCP_VIDEO_MATRIX_CR 0x1bbc +#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd +#define ENCP_MACV_BLANKY_VAL 0x1bc0 +#define ENCP_MACV_MAXY_VAL 0x1bc1 +#define ENCP_MACV_1ST_PSSYNC_STRT 0x1bc2 +#define ENCP_MACV_PSSYNC_STRT 0x1bc3 +#define ENCP_MACV_AGC_STRT 0x1bc4 +#define ENCP_MACV_AGC_END 0x1bc5 +#define ENCP_MACV_WAVE_END 0x1bc6 +#define ENCP_MACV_STRTLINE 0x1bc7 +#define ENCP_MACV_ENDLINE 0x1bc8 +#define ENCP_MACV_TS_CNT_MAX_L 0x1bc9 +#define ENCP_MACV_TS_CNT_MAX_H 0x1bca +#define ENCP_MACV_TIME_DOWN 0x1bcb +#define ENCP_MACV_TIME_LO 0x1bcc +#define ENCP_MACV_TIME_UP 0x1bcd +#define ENCP_MACV_TIME_RST 0x1bce +#define ENCP_VBI_CTRL 0x1bd0 +#define ENCP_VBI_SETTING 0x1bd1 +#define ENCP_VBI_BEGIN 0x1bd2 +#define ENCP_VBI_WIDTH 0x1bd3 +#define ENCP_VBI_HVAL 0x1bd4 +#define ENCP_VBI_DATA0 0x1bd5 +#define ENCP_VBI_DATA1 0x1bd6 +#define C656_HS_ST 0x1be0 +#define C656_HS_ED 0x1be1 +#define C656_VS_LNST_E 0x1be2 +#define C656_VS_LNST_O 0x1be3 +#define C656_VS_LNED_E 0x1be4 +#define C656_VS_LNED_O 0x1be5 +#define C656_FS_LNST 0x1be6 +#define C656_FS_LNED 0x1be7 +#define ENCI_VIDEO_MODE 0x1b00 +#define ENCI_VIDEO_MODE_ADV 0x1b01 +#define ENCI_VIDEO_FSC_ADJ 0x1b02 +#define ENCI_VIDEO_BRIGHT 0x1b03 +#define ENCI_VIDEO_CONT 0x1b04 +#define ENCI_VIDEO_SAT 0x1b05 +#define ENCI_VIDEO_HUE 0x1b06 +#define ENCI_VIDEO_SCH 0x1b07 +#define ENCI_SYNC_MODE 0x1b08 +#define ENCI_SYNC_CTRL 0x1b09 +#define ENCI_SYNC_HSO_BEGIN 0x1b0a +#define ENCI_SYNC_HSO_END 0x1b0b +#define ENCI_SYNC_VSO_EVN 0x1b0c +#define ENCI_SYNC_VSO_ODD 0x1b0d +#define ENCI_SYNC_VSO_EVNLN 0x1b0e +#define ENCI_SYNC_VSO_ODDLN 0x1b0f +#define ENCI_SYNC_HOFFST 0x1b10 +#define ENCI_SYNC_VOFFST 0x1b11 +#define ENCI_SYNC_ADJ 0x1b12 +#define ENCI_RGB_SETTING 0x1b13 +#define ENCI_DE_H_BEGIN 0x1b16 +#define ENCI_DE_H_END 0x1b17 +#define ENCI_DE_V_BEGIN_EVEN 0x1b18 +#define ENCI_DE_V_END_EVEN 0x1b19 +#define ENCI_DE_V_BEGIN_ODD 0x1b1a +#define ENCI_DE_V_END_ODD 0x1b1b +#define ENCI_VBI_SETTING 0x1b20 +#define ENCI_VBI_CCDT_EVN 0x1b21 +#define ENCI_VBI_CCDT_ODD 0x1b22 +#define ENCI_VBI_CC525_LN 0x1b23 +#define ENCI_VBI_CC625_LN 0x1b24 +#define ENCI_VBI_WSSDT 0x1b25 +#define ENCI_VBI_WSS_LN 0x1b26 +#define ENCI_VBI_CGMSDT_L 0x1b27 +#define ENCI_VBI_CGMSDT_H 0x1b28 +#define ENCI_VBI_CGMS_LN 0x1b29 +#define ENCI_VBI_TTX_HTIME 0x1b2a +#define ENCI_VBI_TTX_LN 0x1b2b +#define ENCI_VBI_TTXDT0 0x1b2c +#define ENCI_VBI_TTXDT1 0x1b2d +#define ENCI_VBI_TTXDT2 0x1b2e +#define ENCI_VBI_TTXDT3 0x1b2f +#define ENCI_MACV_N0 0x1b30 +#define ENCI_MACV_N1 0x1b31 +#define ENCI_MACV_N2 0x1b32 +#define ENCI_MACV_N3 0x1b33 +#define ENCI_MACV_N4 0x1b34 +#define ENCI_MACV_N5 0x1b35 +#define ENCI_MACV_N6 0x1b36 +#define ENCI_MACV_N7 0x1b37 +#define ENCI_MACV_N8 0x1b38 +#define ENCI_MACV_N9 0x1b39 +#define ENCI_MACV_N10 0x1b3a +#define ENCI_MACV_N11 0x1b3b +#define ENCI_MACV_N12 0x1b3c +#define ENCI_MACV_N13 0x1b3d +#define ENCI_MACV_N14 0x1b3e +#define ENCI_MACV_N15 0x1b3f +#define ENCI_MACV_N16 0x1b40 +#define ENCI_MACV_N17 0x1b41 +#define ENCI_MACV_N18 0x1b42 +#define ENCI_MACV_N19 0x1b43 +#define ENCI_MACV_N20 0x1b44 +#define ENCI_MACV_N21 0x1b45 +#define ENCI_MACV_N22 0x1b46 +#define ENCI_DBG_PX_RST 0x1b48 +#define ENCI_DBG_FLDLN_RST 0x1b49 +#define ENCI_DBG_PX_INT 0x1b4a +#define ENCI_DBG_FLDLN_INT 0x1b4b +#define ENCI_DBG_MAXPX 0x1b4c +#define ENCI_DBG_MAXLN 0x1b4d +#define ENCI_MACV_MAX_AMP 0x1b50 +#define ENCI_MACV_PULSE_LO 0x1b51 +#define ENCI_MACV_PULSE_HI 0x1b52 +#define ENCI_MACV_BKP_MAX 0x1b53 +#define ENCI_CFILT_CTRL 0x1b54 +#define ENCI_CFILT7 0x1b55 +#define ENCI_YC_DELAY 0x1b56 +#define ENCI_VIDEO_EN 0x1b57 +#define ENCI_DVI_HSO_BEGIN 0x1c00 +#define ENCI_DVI_HSO_END 0x1c01 +#define ENCI_DVI_VSO_BLINE_EVN 0x1c02 +#define ENCI_DVI_VSO_BLINE_ODD 0x1c03 +#define ENCI_DVI_VSO_ELINE_EVN 0x1c04 +#define ENCI_DVI_VSO_ELINE_ODD 0x1c05 +#define ENCI_DVI_VSO_BEGIN_EVN 0x1c06 +#define ENCI_DVI_VSO_BEGIN_ODD 0x1c07 +#define ENCI_DVI_VSO_END_EVN 0x1c08 +#define ENCI_DVI_VSO_END_ODD 0x1c09 +#define ENCI_CFILT_CTRL2 0x1c0a +#define ENCI_DACSEL_0 0x1c0b +#define ENCI_DACSEL_1 0x1c0c +#define ENCP_DACSEL_0 0x1c0d +#define ENCP_DACSEL_1 0x1c0e +#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f +#define ENCI_TST_EN 0x1c10 +#define ENCI_TST_MDSEL 0x1c11 +#define ENCI_TST_Y 0x1c12 +#define ENCI_TST_CB 0x1c13 +#define ENCI_TST_CR 0x1c14 +#define ENCI_TST_CLRBAR_STRT 0x1c15 +#define ENCI_TST_CLRBAR_WIDTH 0x1c16 +#define ENCI_TST_VDCNT_STSET 0x1c17 +#define ENCI_VFIFO2VD_CTL 0x1c18 +#define ENCI_VFIFO2VD_PIXEL_START 0x1c19 +#define ENCI_VFIFO2VD_PIXEL_END 0x1c1a +#define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b +#define ENCI_VFIFO2VD_LINE_TOP_END 0x1c1c +#define ENCI_VFIFO2VD_LINE_BOT_START 0x1c1d +#define ENCI_VFIFO2VD_LINE_BOT_END 0x1c1e +#define ENCI_VFIFO2VD_CTL2 0x1c1f +#define ENCT_VFIFO2VD_CTL 0x1c20 +#define ENCT_VFIFO2VD_PIXEL_START 0x1c21 +#define ENCT_VFIFO2VD_PIXEL_END 0x1c22 +#define ENCT_VFIFO2VD_LINE_TOP_START 0x1c23 +#define ENCT_VFIFO2VD_LINE_TOP_END 0x1c24 +#define ENCT_VFIFO2VD_LINE_BOT_START 0x1c25 +#define ENCT_VFIFO2VD_LINE_BOT_END 0x1c26 +#define ENCT_VFIFO2VD_CTL2 0x1c27 +#define ENCT_TST_EN 0x1c28 +#define ENCT_TST_MDSEL 0x1c29 +#define ENCT_TST_Y 0x1c2a +#define ENCT_TST_CB 0x1c2b +#define ENCT_TST_CR 0x1c2c +#define ENCT_TST_CLRBAR_STRT 0x1c2d +#define ENCT_TST_CLRBAR_WIDTH 0x1c2e +#define ENCT_TST_VDCNT_STSET 0x1c2f +#define ENCP_DVI_HSO_BEGIN 0x1c30 +#define ENCP_DVI_HSO_END 0x1c31 +#define ENCP_DVI_VSO_BLINE_EVN 0x1c32 +#define ENCP_DVI_VSO_BLINE_ODD 0x1c33 +#define ENCP_DVI_VSO_ELINE_EVN 0x1c34 +#define ENCP_DVI_VSO_ELINE_ODD 0x1c35 +#define ENCP_DVI_VSO_BEGIN_EVN 0x1c36 +#define ENCP_DVI_VSO_BEGIN_ODD 0x1c37 +#define ENCP_DVI_VSO_END_EVN 0x1c38 +#define ENCP_DVI_VSO_END_ODD 0x1c39 +#define ENCP_DE_H_BEGIN 0x1c3a +#define ENCP_DE_H_END 0x1c3b +#define ENCP_DE_V_BEGIN_EVEN 0x1c3c +#define ENCP_DE_V_END_EVEN 0x1c3d +#define ENCP_DE_V_BEGIN_ODD 0x1c3e +#define ENCP_DE_V_END_ODD 0x1c3f +#define ENCI_SYNC_LINE_LENGTH 0x1c40 +#define ENCI_SYNC_PIXEL_EN 0x1c41 +#define ENCI_SYNC_TO_LINE_EN 0x1c42 +#define ENCI_SYNC_TO_PIXEL 0x1c43 +#define ENCP_SYNC_LINE_LENGTH 0x1c44 +#define ENCP_SYNC_PIXEL_EN 0x1c45 +#define ENCP_SYNC_TO_LINE_EN 0x1c46 +#define ENCP_SYNC_TO_PIXEL 0x1c47 +#define ENCT_SYNC_LINE_LENGTH 0x1c48 +#define ENCT_SYNC_PIXEL_EN 0x1c49 +#define ENCT_SYNC_TO_LINE_EN 0x1c4a +#define ENCT_SYNC_TO_PIXEL 0x1c4b +#define ENCL_SYNC_LINE_LENGTH 0x1c4c +#define ENCL_SYNC_PIXEL_EN 0x1c4d +#define ENCL_SYNC_TO_LINE_EN 0x1c4e +#define ENCL_SYNC_TO_PIXEL 0x1c4f +#define ENCP_VFIFO2VD_CTL2 0x1c50 +#define VENC_DVI_SETTING_MORE 0x1c51 +#define VENC_VDAC_DAC4_FILT_CTRL0 0x1c54 +#define VENC_VDAC_DAC4_FILT_CTRL1 0x1c55 +#define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56 +#define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57 +#define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58 +#define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59 +#define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a +#define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b +#define VENC_VDAC_DAC2_FILT_CTRL0 0x1c5c +#define VENC_VDAC_DAC2_FILT_CTRL1 0x1c5d +#define VENC_VDAC_DAC3_FILT_CTRL0 0x1c5e +#define VENC_VDAC_DAC3_FILT_CTRL1 0x1c5f +#define ENCT_VIDEO_EN 0x1c60 +#define ENCT_VIDEO_Y_SCL 0x1c61 +#define ENCT_VIDEO_PB_SCL 0x1c62 +#define ENCT_VIDEO_PR_SCL 0x1c63 +#define ENCT_VIDEO_Y_OFFST 0x1c64 +#define ENCT_VIDEO_PB_OFFST 0x1c65 +#define ENCT_VIDEO_PR_OFFST 0x1c66 +#define ENCT_VIDEO_MODE 0x1c67 +#define ENCT_VIDEO_MODE_ADV 0x1c68 +#define ENCT_DBG_PX_RST 0x1c69 +#define ENCT_DBG_LN_RST 0x1c6a +#define ENCT_DBG_PX_INT 0x1c6b +#define ENCT_DBG_LN_INT 0x1c6c +#define ENCT_VIDEO_YFP1_HTIME 0x1c6d +#define ENCT_VIDEO_YFP2_HTIME 0x1c6e +#define ENCT_VIDEO_YC_DLY 0x1c6f +#define ENCT_VIDEO_MAX_PXCNT 0x1c70 +#define ENCT_VIDEO_HAVON_END 0x1c71 +#define ENCT_VIDEO_HAVON_BEGIN 0x1c72 +#define ENCT_VIDEO_VAVON_ELINE 0x1c73 +#define ENCT_VIDEO_VAVON_BLINE 0x1c74 +#define ENCT_VIDEO_HSO_BEGIN 0x1c75 +#define ENCT_VIDEO_HSO_END 0x1c76 +#define ENCT_VIDEO_VSO_BEGIN 0x1c77 +#define ENCT_VIDEO_VSO_END 0x1c78 +#define ENCT_VIDEO_VSO_BLINE 0x1c79 +#define ENCT_VIDEO_VSO_ELINE 0x1c7a +#define ENCT_VIDEO_MAX_LNCNT 0x1c7b +#define ENCT_VIDEO_BLANKY_VAL 0x1c7c +#define ENCT_VIDEO_BLANKPB_VAL 0x1c7d +#define ENCT_VIDEO_BLANKPR_VAL 0x1c7e +#define ENCT_VIDEO_HOFFST 0x1c7f +#define ENCT_VIDEO_VOFFST 0x1c80 +#define ENCT_VIDEO_RGB_CTRL 0x1c81 +#define ENCT_VIDEO_FILT_CTRL 0x1c82 +#define ENCT_VIDEO_OFLD_VPEQ_OFST 0x1c83 +#define ENCT_VIDEO_OFLD_VOAV_OFST 0x1c84 +#define ENCT_VIDEO_MATRIX_CB 0x1c85 +#define ENCT_VIDEO_MATRIX_CR 0x1c86 +#define ENCT_VIDEO_RGBIN_CTRL 0x1c87 +#define ENCT_MAX_LINE_SWITCH_POINT 0x1c88 +#define ENCT_DACSEL_0 0x1c89 +#define ENCT_DACSEL_1 0x1c8a +#define ENCL_VFIFO2VD_CTL 0x1c90 +#define ENCL_VFIFO2VD_PIXEL_START 0x1c91 +#define ENCL_VFIFO2VD_PIXEL_END 0x1c92 +#define ENCL_VFIFO2VD_LINE_TOP_START 0x1c93 +#define ENCL_VFIFO2VD_LINE_TOP_END 0x1c94 +#define ENCL_VFIFO2VD_LINE_BOT_START 0x1c95 +#define ENCL_VFIFO2VD_LINE_BOT_END 0x1c96 +#define ENCL_VFIFO2VD_CTL2 0x1c97 +#define ENCL_TST_EN 0x1c98 +#define ENCL_TST_MDSEL 0x1c99 +#define ENCL_TST_Y 0x1c9a +#define ENCL_TST_CB 0x1c9b +#define ENCL_TST_CR 0x1c9c +#define ENCL_TST_CLRBAR_STRT 0x1c9d +#define ENCL_TST_CLRBAR_WIDTH 0x1c9e +#define ENCL_TST_VDCNT_STSET 0x1c9f +#define ENCL_VIDEO_EN 0x1ca0 +#define ENCL_VIDEO_Y_SCL 0x1ca1 +#define ENCL_VIDEO_PB_SCL 0x1ca2 +#define ENCL_VIDEO_PR_SCL 0x1ca3 +#define ENCL_VIDEO_Y_OFFST 0x1ca4 +#define ENCL_VIDEO_PB_OFFST 0x1ca5 +#define ENCL_VIDEO_PR_OFFST 0x1ca6 +#define ENCL_VIDEO_MODE 0x1ca7 +#define ENCL_VIDEO_MODE_ADV 0x1ca8 +#define ENCL_DBG_PX_RST 0x1ca9 +#define ENCL_DBG_LN_RST 0x1caa +#define ENCL_DBG_PX_INT 0x1cab +#define ENCL_DBG_LN_INT 0x1cac +#define ENCL_VIDEO_YFP1_HTIME 0x1cad +#define ENCL_VIDEO_YFP2_HTIME 0x1cae +#define ENCL_VIDEO_YC_DLY 0x1caf +#define ENCL_VIDEO_MAX_PXCNT 0x1cb0 +#define ENCL_VIDEO_HAVON_END 0x1cb1 +#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2 +#define ENCL_VIDEO_VAVON_ELINE 0x1cb3 +#define ENCL_VIDEO_VAVON_BLINE 0x1cb4 +#define ENCL_VIDEO_HSO_BEGIN 0x1cb5 +#define ENCL_VIDEO_HSO_END 0x1cb6 +#define ENCL_VIDEO_VSO_BEGIN 0x1cb7 +#define ENCL_VIDEO_VSO_END 0x1cb8 +#define ENCL_VIDEO_VSO_BLINE 0x1cb9 +#define ENCL_VIDEO_VSO_ELINE 0x1cba +#define ENCL_VIDEO_MAX_LNCNT 0x1cbb +#define ENCL_VIDEO_BLANKY_VAL 0x1cbc +#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd +#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe +#define ENCL_VIDEO_HOFFST 0x1cbf +#define ENCL_VIDEO_VOFFST 0x1cc0 +#define ENCL_VIDEO_RGB_CTRL 0x1cc1 +#define ENCL_VIDEO_FILT_CTRL 0x1cc2 +#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3 +#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4 +#define ENCL_VIDEO_MATRIX_CB 0x1cc5 +#define ENCL_VIDEO_MATRIX_CR 0x1cc6 +#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7 +#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8 +#define ENCL_DACSEL_0 0x1cc9 +#define ENCL_DACSEL_1 0x1cca +#define RDMA_AHB_START_ADDR_MAN 0x1100 +#define RDMA_AHB_END_ADDR_MAN 0x1101 +#define RDMA_AHB_START_ADDR_1 0x1102 +#define RDMA_AHB_END_ADDR_1 0x1103 +#define RDMA_AHB_START_ADDR_2 0x1104 +#define RDMA_AHB_END_ADDR_2 0x1105 +#define RDMA_AHB_START_ADDR_3 0x1106 +#define RDMA_AHB_END_ADDR_3 0x1107 +#define RDMA_AHB_START_ADDR_4 0x1108 +#define RDMA_AHB_END_ADDR_4 0x1109 +#define RDMA_AHB_START_ADDR_5 0x110a +#define RDMA_AHB_END_ADDR_5 0x110b +#define RDMA_AHB_START_ADDR_6 0x110c +#define RDMA_AHB_END_ADDR_6 0x110d +#define RDMA_AHB_START_ADDR_7 0x110e +#define RDMA_AHB_END_ADDR_7 0x110f +#define RDMA_ACCESS_AUTO 0x1110 +#define RDMA_ACCESS_AUTO2 0x1111 +#define RDMA_ACCESS_AUTO3 0x1112 +#define RDMA_ACCESS_MAN 0x1113 +#define RDMA_CTRL 0x1114 +#define RDMA_STATUS 0x1115 +#define RDMA_STATUS2 0x1116 +#define RDMA_STATUS3 0x1117 +#define L_GAMMA_CNTL_PORT 0x1400 +#define L_GAMMA_DATA_PORT 0x1401 +#define L_GAMMA_ADDR_PORT 0x1402 +#define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403 +#define L_RGB_BASE_ADDR 0x1405 +#define L_RGB_COEFF_ADDR 0x1406 +#define L_POL_CNTL_ADDR 0x1407 +#define L_DITH_CNTL_ADDR 0x1408 +#define L_GAMMA_PROBE_CTRL 0x1409 +#define L_GAMMA_PROBE_COLOR_L 0x140a +#define L_GAMMA_PROBE_COLOR_H 0x140b +#define L_GAMMA_PROBE_HL_COLOR 0x140c +#define L_GAMMA_PROBE_POS_X 0x140d +#define L_GAMMA_PROBE_POS_Y 0x140e +#define L_STH1_HS_ADDR 0x1410 +#define L_STH1_HE_ADDR 0x1411 +#define L_STH1_VS_ADDR 0x1412 +#define L_STH1_VE_ADDR 0x1413 +#define L_STH2_HS_ADDR 0x1414 +#define L_STH2_HE_ADDR 0x1415 +#define L_STH2_VS_ADDR 0x1416 +#define L_STH2_VE_ADDR 0x1417 +#define L_OEH_HS_ADDR 0x1418 +#define L_OEH_HE_ADDR 0x1419 +#define L_OEH_VS_ADDR 0x141a +#define L_OEH_VE_ADDR 0x141b +#define L_VCOM_HSWITCH_ADDR 0x141c +#define L_VCOM_VS_ADDR 0x141d +#define L_VCOM_VE_ADDR 0x141e +#define L_CPV1_HS_ADDR 0x141f +#define L_CPV1_HE_ADDR 0x1420 +#define L_CPV1_VS_ADDR 0x1421 +#define L_CPV1_VE_ADDR 0x1422 +#define L_CPV2_HS_ADDR 0x1423 +#define L_CPV2_HE_ADDR 0x1424 +#define L_CPV2_VS_ADDR 0x1425 +#define L_CPV2_VE_ADDR 0x1426 +#define L_STV1_HS_ADDR 0x1427 +#define L_STV1_HE_ADDR 0x1428 +#define L_STV1_VS_ADDR 0x1429 +#define L_STV1_VE_ADDR 0x142a +#define L_STV2_HS_ADDR 0x142b +#define L_STV2_HE_ADDR 0x142c +#define L_STV2_VS_ADDR 0x142d +#define L_STV2_VE_ADDR 0x142e +#define L_OEV1_HS_ADDR 0x142f +#define L_OEV1_HE_ADDR 0x1430 +#define L_OEV1_VS_ADDR 0x1431 +#define L_OEV1_VE_ADDR 0x1432 +#define L_OEV2_HS_ADDR 0x1433 +#define L_OEV2_HE_ADDR 0x1434 +#define L_OEV2_VS_ADDR 0x1435 +#define L_OEV2_VE_ADDR 0x1436 +#define L_OEV3_HS_ADDR 0x1437 +#define L_OEV3_HE_ADDR 0x1438 +#define L_OEV3_VS_ADDR 0x1439 +#define L_OEV3_VE_ADDR 0x143a +#define L_LCD_PWR_ADDR 0x143b +#define L_LCD_PWM0_LO_ADDR 0x143c +#define L_LCD_PWM0_HI_ADDR 0x143d +#define L_LCD_PWM1_LO_ADDR 0x143e +#define L_LCD_PWM1_HI_ADDR 0x143f +#define L_INV_CNT_ADDR 0x1440 +#define L_TCON_MISC_SEL_ADDR 0x1441 +#define L_DUAL_PORT_CNTL_ADDR 0x1442 +#define MLVDS_CLK_CTL1_HI 0x1443 +#define MLVDS_CLK_CTL1_LO 0x1444 +#define L_TCON_DOUBLE_CTL 0x1449 +#define L_TCON_PATTERN_HI 0x144a +#define L_TCON_PATTERN_LO 0x144b +#define LDIM_BL_ADDR_PORT 0x144e +#define LDIM_BL_DATA_PORT 0x144f +#define L_DE_HS_ADDR 0x1451 +#define L_DE_HE_ADDR 0x1452 +#define L_DE_VS_ADDR 0x1453 +#define L_DE_VE_ADDR 0x1454 +#define L_HSYNC_HS_ADDR 0x1455 +#define L_HSYNC_HE_ADDR 0x1456 +#define L_HSYNC_VS_ADDR 0x1457 +#define L_HSYNC_VE_ADDR 0x1458 +#define L_VSYNC_HS_ADDR 0x1459 +#define L_VSYNC_HE_ADDR 0x145a +#define L_VSYNC_VS_ADDR 0x145b +#define L_VSYNC_VE_ADDR 0x145c +#define L_LCD_MCU_CTL 0x145d +#define DUAL_MLVDS_CTL 0x1460 +#define DUAL_MLVDS_LINE_START 0x1461 +#define DUAL_MLVDS_LINE_END 0x1462 +#define DUAL_MLVDS_PIXEL_W_START_L 0x1463 +#define DUAL_MLVDS_PIXEL_W_END_L 0x1464 +#define DUAL_MLVDS_PIXEL_W_START_R 0x1465 +#define DUAL_MLVDS_PIXEL_W_END_R 0x1466 +#define DUAL_MLVDS_PIXEL_R_START_L 0x1467 +#define DUAL_MLVDS_PIXEL_R_CNT_L 0x1468 +#define DUAL_MLVDS_PIXEL_R_START_R 0x1469 +#define DUAL_MLVDS_PIXEL_R_CNT_R 0x146a +#define V_INVERSION_PIXEL 0x1470 +#define V_INVERSION_LINE 0x1471 +#define V_INVERSION_CONTROL 0x1472 +#define MLVDS2_CONTROL 0x1474 +#define MLVDS2_CONFIG_HI 0x1475 +#define MLVDS2_CONFIG_LO 0x1476 +#define MLVDS2_DUAL_GATE_WR_START 0x1477 +#define MLVDS2_DUAL_GATE_WR_END 0x1478 +#define MLVDS2_DUAL_GATE_RD_START 0x1479 +#define MLVDS2_DUAL_GATE_RD_END 0x147a +#define MLVDS2_SECOND_RESET_CTL 0x147b +#define MLVDS2_DUAL_GATE_CTL_HI 0x147c +#define MLVDS2_DUAL_GATE_CTL_LO 0x147d +#define MLVDS2_RESET_CONFIG_HI 0x147e +#define MLVDS2_RESET_CONFIG_LO 0x147f +#define GAMMA_CNTL_PORT 0x1480 +#define GAMMA_DATA_PORT 0x1481 +#define GAMMA_ADDR_PORT 0x1482 +#define GAMMA_VCOM_HSWITCH_ADDR 0x1483 +#define RGB_BASE_ADDR 0x1485 +#define RGB_COEFF_ADDR 0x1486 +#define POL_CNTL_ADDR 0x1487 +#define DITH_CNTL_ADDR 0x1488 +#define GAMMA_PROBE_CTRL 0x1489 +#define GAMMA_PROBE_COLOR_L 0x148a +#define GAMMA_PROBE_COLOR_H 0x148b +#define GAMMA_PROBE_HL_COLOR 0x148c +#define GAMMA_PROBE_POS_X 0x148d +#define GAMMA_PROBE_POS_Y 0x148e +#define STH1_HS_ADDR 0x1490 +#define STH1_HE_ADDR 0x1491 +#define STH1_VS_ADDR 0x1492 +#define STH1_VE_ADDR 0x1493 +#define STH2_HS_ADDR 0x1494 +#define STH2_HE_ADDR 0x1495 +#define STH2_VS_ADDR 0x1496 +#define STH2_VE_ADDR 0x1497 +#define OEH_HS_ADDR 0x1498 +#define OEH_HE_ADDR 0x1499 +#define OEH_VS_ADDR 0x149a +#define OEH_VE_ADDR 0x149b +#define VCOM_HSWITCH_ADDR 0x149c +#define VCOM_VS_ADDR 0x149d +#define VCOM_VE_ADDR 0x149e +#define CPV1_HS_ADDR 0x149f +#define CPV1_HE_ADDR 0x14a0 +#define CPV1_VS_ADDR 0x14a1 +#define CPV1_VE_ADDR 0x14a2 +#define CPV2_HS_ADDR 0x14a3 +#define CPV2_HE_ADDR 0x14a4 +#define CPV2_VS_ADDR 0x14a5 +#define CPV2_VE_ADDR 0x14a6 +#define STV1_HS_ADDR 0x14a7 +#define STV1_HE_ADDR 0x14a8 +#define STV1_VS_ADDR 0x14a9 +#define STV1_VE_ADDR 0x14aa +#define STV2_HS_ADDR 0x14ab +#define STV2_HE_ADDR 0x14ac +#define STV2_VS_ADDR 0x14ad +#define STV2_VE_ADDR 0x14ae +#define OEV1_HS_ADDR 0x14af +#define OEV1_HE_ADDR 0x14b0 +#define OEV1_VS_ADDR 0x14b1 +#define OEV1_VE_ADDR 0x14b2 +#define OEV2_HS_ADDR 0x14b3 +#define OEV2_HE_ADDR 0x14b4 +#define OEV2_VS_ADDR 0x14b5 +#define OEV2_VE_ADDR 0x14b6 +#define OEV3_HS_ADDR 0x14b7 +#define OEV3_HE_ADDR 0x14b8 +#define OEV3_VS_ADDR 0x14b9 +#define OEV3_VE_ADDR 0x14ba +#define LCD_PWR_ADDR 0x14bb +#define LCD_PWM0_LO_ADDR 0x14bc +#define LCD_PWM0_HI_ADDR 0x14bd +#define LCD_PWM1_LO_ADDR 0x14be +#define LCD_PWM1_HI_ADDR 0x14bf +#define INV_CNT_ADDR 0x14c0 +#define TCON_MISC_SEL_ADDR 0x14c1 +#define DUAL_PORT_CNTL_ADDR 0x14c2 +#define MLVDS_CONTROL 0x14c3 +#define MLVDS_RESET_PATTERN_HI 0x14c4 +#define MLVDS_RESET_PATTERN_LO 0x14c5 +#define MLVDS_RESET_PATTERN_EXT 0x14c6 +#define MLVDS_CONFIG_HI 0x14c7 +#define MLVDS_CONFIG_LO 0x14c8 +#define TCON_DOUBLE_CTL 0x14c9 +#define TCON_PATTERN_HI 0x14ca +#define TCON_PATTERN_LO 0x14cb +#define TCON_CONTROL_HI 0x14cc +#define TCON_CONTROL_LO 0x14cd +#define LVDS_BLANK_DATA_HI 0x14ce +#define LVDS_BLANK_DATA_LO 0x14cf +#define LVDS_PACK_CNTL_ADDR 0x14d0 +#define DE_HS_ADDR 0x14d1 +#define DE_HE_ADDR 0x14d2 +#define DE_VS_ADDR 0x14d3 +#define DE_VE_ADDR 0x14d4 +#define HSYNC_HS_ADDR 0x14d5 +#define HSYNC_HE_ADDR 0x14d6 +#define HSYNC_VS_ADDR 0x14d7 +#define HSYNC_VE_ADDR 0x14d8 +#define VSYNC_HS_ADDR 0x14d9 +#define VSYNC_HE_ADDR 0x14da +#define VSYNC_VS_ADDR 0x14db +#define VSYNC_VE_ADDR 0x14dc +#define LCD_MCU_CTL 0x14dd +#define LCD_MCU_DATA_0 0x14de +#define LCD_MCU_DATA_1 0x14df +#define LVDS_GEN_CNTL 0x14e0 +#define LVDS_PHY_CNTL0 0x14e1 +#define LVDS_PHY_CNTL1 0x14e2 +#define LVDS_PHY_CNTL2 0x14e3 +#define LVDS_PHY_CNTL3 0x14e4 +#define LVDS_PHY_CNTL4 0x14e5 +#define LVDS_PHY_CNTL5 0x14e6 +#define LVDS_SRG_TEST 0x14e8 +#define LVDS_BIST_MUX0 0x14e9 +#define LVDS_BIST_MUX1 0x14ea +#define LVDS_BIST_FIXED0 0x14eb +#define LVDS_BIST_FIXED1 0x14ec +#define LVDS_BIST_CNTL0 0x14ed +#define LVDS_CLKB_CLKA 0x14ee +#define LVDS_PHY_CLK_CNTL 0x14ef +#define LVDS_SER_EN 0x14f0 +#define LVDS_PHY_CNTL6 0x14f1 +#define LVDS_PHY_CNTL7 0x14f2 +#define LVDS_PHY_CNTL8 0x14f3 +#define MLVDS_CLK_CTL0_HI 0x14f4 +#define MLVDS_CLK_CTL0_LO 0x14f5 +#define MLVDS_DUAL_GATE_WR_START 0x14f6 +#define MLVDS_DUAL_GATE_WR_END 0x14f7 +#define MLVDS_DUAL_GATE_RD_START 0x14f8 +#define MLVDS_DUAL_GATE_RD_END 0x14f9 +#define MLVDS_SECOND_RESET_CTL 0x14fa +#define MLVDS_DUAL_GATE_CTL_HI 0x14fb +#define MLVDS_DUAL_GATE_CTL_LO 0x14fc +#define MLVDS_RESET_CONFIG_HI 0x14fd +#define MLVDS_RESET_CONFIG_LO 0x14fe +#define VPU_OSD1_MMC_CTRL 0x2701 +#define VPU_OSD2_MMC_CTRL 0x2702 +#define VPU_VD1_MMC_CTRL 0x2703 +#define VPU_VD2_MMC_CTRL 0x2704 +#define VPU_DI_IF1_MMC_CTRL 0x2705 +#define VPU_DI_MEM_MMC_CTRL 0x2706 +#define VPU_DI_INP_MMC_CTRL 0x2707 +#define VPU_DI_MTNRD_MMC_CTRL 0x2708 +#define VPU_DI_CHAN2_MMC_CTRL 0x2709 +#define VPU_DI_MTNWR_MMC_CTRL 0x270a +#define VPU_DI_NRWR_MMC_CTRL 0x270b +#define VPU_DI_DIWR_MMC_CTRL 0x270c +#define VPU_VDIN0_MMC_CTRL 0x270d +#define VPU_VDIN1_MMC_CTRL 0x270e +#define VPU_BT656_MMC_CTRL 0x270f +#define VPU_TVD3D_MMC_CTRL 0x2710 +#define VPU_TVDVBI_MMC_CTRL 0x2711 +#define VPU_TVDVBI_VSLATCH_ADDR 0x2712 +#define VPU_TVDVBI_WRRSP_ADDR 0x2713 +#define VPU_VDIN_PRE_ARB_CTRL 0x2714 +#define VPU_VDISP_PRE_ARB_CTRL 0x2715 +#define VPU_VPUARB2_PRE_ARB_CTRL 0x2716 +#define VPU_OSD3_MMC_CTRL 0x2717 +#define VPU_OSD4_MMC_CTRL 0x2718 +#define VPU_VD3_MMC_CTRL 0x2719 +#define VPU_VIU_VENC_MUX_CTRL 0x271a +#define VIU1_SEL_VENC_MASK 0x3 +#define VIU1_SEL_VENC_ENCL 0 +#define VIU1_SEL_VENC_ENCI 1 +#define VIU1_SEL_VENC_ENCP 2 +#define VIU1_SEL_VENC_ENCT 3 +#define VIU2_SEL_VENC_MASK 0xc +#define VIU2_SEL_VENC_ENCL 0 +#define VIU2_SEL_VENC_ENCI (1 << 2) +#define VIU2_SEL_VENC_ENCP (2 << 2) +#define VIU2_SEL_VENC_ENCT (3 << 2) +#define VPU_HDMI_SETTING 0x271b +#define ENCI_INFO_READ 0x271c +#define ENCP_INFO_READ 0x271d +#define ENCT_INFO_READ 0x271e +#define ENCL_INFO_READ 0x271f +#define VPU_SW_RESET 0x2720 +#define VPU_D2D3_MMC_CTRL 0x2721 +#define VPU_CONT_MMC_CTRL 0x2722 +#define VPU_CLK_GATE 0x2723 +#define VPU_RDMA_MMC_CTRL 0x2724 +#define VPU_MEM_PD_REG0 0x2725 +#define VPU_MEM_PD_REG1 0x2726 +#define VPU_HDMI_DATA_OVR 0x2727 +#define VPU_PROT1_MMC_CTRL 0x2728 +#define VPU_PROT2_MMC_CTRL 0x2729 +#define VPU_PROT3_MMC_CTRL 0x272a +#define VPU_ARB4_V1_MMC_CTRL 0x272b +#define VPU_ARB4_V2_MMC_CTRL 0x272c +#define VPU_VPU_PWM_V0 0x2730 +#define VPU_VPU_PWM_V1 0x2731 +#define VPU_VPU_PWM_V2 0x2732 +#define VPU_VPU_PWM_V3 0x2733 +#define VPU_VPU_PWM_H0 0x2734 +#define VPU_VPU_PWM_H1 0x2735 +#define VPU_VPU_PWM_H2 0x2736 +#define VPU_VPU_PWM_H3 0x2737 +#define VPU_MISC_CTRL 0x2740 +#define VPU_ISP_GCLK_CTRL0 0x2741 +#define VPU_ISP_GCLK_CTRL1 0x2742 +#define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743 +#define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744 +#define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745 + +#define VPU_PROT1_CLK_GATE 0x2750 +#define VPU_PROT1_GEN_CNTL 0x2751 +#define VPU_PROT1_X_START_END 0x2752 +#define VPU_PROT1_Y_START_END 0x2753 +#define VPU_PROT1_Y_LEN_STEP 0x2754 +#define VPU_PROT1_RPT_LOOP 0x2755 +#define VPU_PROT1_RPT_PAT 0x2756 +#define VPU_PROT1_DDR 0x2757 +#define VPU_PROT1_RBUF_ROOM 0x2758 +#define VPU_PROT1_STAT_0 0x2759 +#define VPU_PROT1_STAT_1 0x275a +#define VPU_PROT1_STAT_2 0x275b +#define VPU_PROT1_REQ_ONOFF 0x275c +#define VPU_PROT2_CLK_GATE 0x2760 +#define VPU_PROT2_GEN_CNTL 0x2761 +#define VPU_PROT2_X_START_END 0x2762 +#define VPU_PROT2_Y_START_END 0x2763 +#define VPU_PROT2_Y_LEN_STEP 0x2764 +#define VPU_PROT2_RPT_LOOP 0x2765 +#define VPU_PROT2_RPT_PAT 0x2766 +#define VPU_PROT2_DDR 0x2767 +#define VPU_PROT2_RBUF_ROOM 0x2768 +#define VPU_PROT2_STAT_0 0x2769 +#define VPU_PROT2_STAT_1 0x276a +#define VPU_PROT2_STAT_2 0x276b +#define VPU_PROT2_REQ_ONOFF 0x276c +#define VPU_PROT3_CLK_GATE 0x2770 +#define VPU_PROT3_GEN_CNTL 0x2771 +#define VPU_PROT3_X_START_END 0x2772 +#define VPU_PROT3_Y_START_END 0x2773 +#define VPU_PROT3_Y_LEN_STEP 0x2774 +#define VPU_PROT3_RPT_LOOP 0x2775 +#define VPU_PROT3_RPT_PAT 0x2776 +#define VPU_PROT3_DDR 0x2777 +#define VPU_PROT3_RBUF_ROOM 0x2778 +#define VPU_PROT3_STAT_0 0x2779 +#define VPU_PROT3_STAT_1 0x277a +#define VPU_PROT3_STAT_2 0x277b +#define VPU_PROT3_REQ_ONOFF 0x277c + +/* osd super scale */ +#define OSDSR_HV_SIZEIN 0x3130 +#define OSDSR_CTRL_MODE 0x3131 +#define OSDSR_ABIC_HCOEF 0x3132 +#define OSDSR_YBIC_HCOEF 0x3133 +#define OSDSR_CBIC_HCOEF 0x3134 +#define OSDSR_ABIC_VCOEF 0x3135 +#define OSDSR_YBIC_VCOEF 0x3136 +#define OSDSR_CBIC_VCOEF 0x3137 +#define OSDSR_VAR_PARA 0x3138 +#define OSDSR_CONST_PARA 0x3139 +#define OSDSR_RKE_EXTWIN 0x313a +#define OSDSR_UK_GRAD2DDIAG_TH_RATE 0x313b +#define OSDSR_UK_GRAD2DDIAG_LIMIT 0x313c +#define OSDSR_UK_GRAD2DADJA_TH_RATE 0x313d +#define OSDSR_UK_GRAD2DADJA_LIMIT 0x313e +#define OSDSR_UK_BST_GAIN 0x313f +#define OSDSR_HVBLEND_TH 0x3140 +#define OSDSR_DEMO_WIND_TB 0x3141 +#define OSDSR_DEMO_WIND_LR 0x3142 +#define OSDSR_INT_BLANK_NUM 0x3143 +#define OSDSR_FRM_END_STAT 0x3144 +#define OSDSR_ABIC_HCOEF0 0x3145 +#define OSDSR_YBIC_HCOEF0 0x3146 +#define OSDSR_CBIC_HCOEF0 0x3147 +#define OSDSR_ABIC_VCOEF0 0x3148 +#define OSDSR_YBIC_VCOEF0 0x3149 +#define OSDSR_CBIC_VCOEF0 0x314a + +#endif /* __MESON_REGISTERS_H */ diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c new file mode 100644 index 000000000000..252cfd4b19b1 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include "meson_drv.h" +#include "meson_vclk.h" + +/* + * VCLK is the "Pixel Clock" frequency generator from a dedicated PLL. + * We handle the following encodings : + * - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks + * + * What is missing : + * - HDMI Pixel Clocks generation + */ + +/* HHI Registers */ +#define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */ +#define VID_PLL_EN BIT(19) +#define VID_PLL_BYPASS BIT(18) +#define VID_PLL_PRESET BIT(15) +#define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */ +#define VCLK2_DIV_MASK 0xff +#define VCLK2_DIV_EN BIT(16) +#define VCLK2_DIV_RESET BIT(17) +#define CTS_VDAC_SEL_MASK (0xf << 28) +#define CTS_VDAC_SEL_SHIFT 28 +#define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */ +#define VCLK2_EN BIT(19) +#define VCLK2_SEL_MASK (0x7 << 16) +#define VCLK2_SEL_SHIFT 16 +#define VCLK2_SOFT_RESET BIT(15) +#define VCLK2_DIV1_EN BIT(0) +#define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */ +#define CTS_ENCI_SEL_MASK (0xf << 28) +#define CTS_ENCI_SEL_SHIFT 28 +#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */ +#define CTS_ENCI_EN BIT(0) +#define CTS_VDAC_EN BIT(4) + +#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ +#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ + +#define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ +#define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */ +#define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */ +#define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */ +#define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */ +#define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */ + +#define HDMI_PLL_RESET BIT(28) +#define HDMI_PLL_LOCK BIT(31) + +/* + * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC + * + * TOFIX: Refactor into table to also handle HDMI frequency and paths + */ +static void meson_venci_cvbs_clock_config(struct meson_drm *priv) +{ + unsigned int val; + + /* Setup PLL to output 1.485GHz */ + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) { + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00404e00); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d); + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0xa6212844); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c4d000c); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); + + /* Reset PLL */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, + HDMI_PLL_RESET, HDMI_PLL_RESET); + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, + HDMI_PLL_RESET, 0); + } + + /* Poll for lock bit */ + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val, + (val & HDMI_PLL_LOCK), 10, 0); + + /* Disable VCLK2 */ + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0); + + /* Disable vid_pll output clock */ + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0); + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0); + /* Enable vid_pll bypass to HDMI pll */ + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, + VID_PLL_BYPASS, VID_PLL_BYPASS); + /* Enable the vid_pll output clock */ + regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, + VID_PLL_EN, VID_PLL_EN); + + /* Setup the VCLK2 divider value to achieve 27MHz */ + regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV, + VCLK2_DIV_MASK, (55 - 1)); + + /* select vid_pll for vclk2 */ + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, + VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT)); + /* enable vclk2 gate */ + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN); + + /* select vclk_div1 for enci */ + regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV, + CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT)); + /* select vclk_div1 for vdac */ + regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV, + CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT)); + + /* release vclk2_div_reset and enable vclk2_div */ + regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV, + VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN); + + /* enable vclk2_div1 gate */ + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, + VCLK2_DIV1_EN, VCLK2_DIV1_EN); + + /* reset vclk2 */ + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, + VCLK2_SOFT_RESET, VCLK2_SOFT_RESET); + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, + VCLK2_SOFT_RESET, 0); + + /* enable enci_clk */ + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2, + CTS_ENCI_EN, CTS_ENCI_EN); + /* enable vdac_clk */ + regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2, + CTS_VDAC_EN, CTS_VDAC_EN); +} + +void meson_vclk_setup(struct meson_drm *priv, unsigned int target, + unsigned int freq) +{ + if (target == MESON_VCLK_TARGET_CVBS && freq == MESON_VCLK_CVBS) + meson_venci_cvbs_clock_config(priv); +} diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h new file mode 100644 index 000000000000..ec62735996de --- /dev/null +++ b/drivers/gpu/drm/meson/meson_vclk.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* Video Clock */ + +#ifndef __MESON_VCLK_H +#define __MESON_VCLK_H + +enum { + MESON_VCLK_TARGET_CVBS = 0, +}; + +/* 27MHz is the CVBS Pixel Clock */ +#define MESON_VCLK_CVBS 27000 + +void meson_vclk_setup(struct meson_drm *priv, unsigned int target, + unsigned int freq); + +#endif /* __MESON_VCLK_H */ diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c new file mode 100644 index 000000000000..d836b2274531 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_venc.c @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include "meson_drv.h" +#include "meson_venc.h" +#include "meson_vpp.h" +#include "meson_vclk.h" +#include "meson_registers.h" + +/* + * VENC Handle the pixels encoding to the output formats. + * We handle the following encodings : + * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter + * + * What is missing : + * - TMDS/HDMI Encoding via ENCI_DIV and ENCP + * - Setup of more clock rates for HDMI modes + * - LCD Panel encoding via ENCL + * - TV Panel encoding via ENCT + */ + +struct meson_cvbs_enci_mode meson_cvbs_enci_pal = { + .mode_tag = MESON_VENC_MODE_CVBS_PAL, + .hso_begin = 3, + .hso_end = 129, + .vso_even = 3, + .vso_odd = 260, + .macv_max_amp = 7, + .video_prog_mode = 0xff, + .video_mode = 0x13, + .sch_adjust = 0x28, + .yc_delay = 0x343, + .pixel_start = 251, + .pixel_end = 1691, + .top_field_line_start = 22, + .top_field_line_end = 310, + .bottom_field_line_start = 23, + .bottom_field_line_end = 311, + .video_saturation = 9, + .video_contrast = 0, + .video_brightness = 0, + .video_hue = 0, + .analog_sync_adj = 0x8080, +}; + +struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = { + .mode_tag = MESON_VENC_MODE_CVBS_NTSC, + .hso_begin = 5, + .hso_end = 129, + .vso_even = 3, + .vso_odd = 260, + .macv_max_amp = 0xb, + .video_prog_mode = 0xf0, + .video_mode = 0x8, + .sch_adjust = 0x20, + .yc_delay = 0x333, + .pixel_start = 227, + .pixel_end = 1667, + .top_field_line_start = 18, + .top_field_line_end = 258, + .bottom_field_line_start = 19, + .bottom_field_line_end = 259, + .video_saturation = 18, + .video_contrast = 3, + .video_brightness = 0, + .video_hue = 0, + .analog_sync_adj = 0x9c00, +}; + +void meson_venci_cvbs_mode_set(struct meson_drm *priv, + struct meson_cvbs_enci_mode *mode) +{ + if (mode->mode_tag == priv->venc.current_mode) + return; + + /* CVBS Filter settings */ + writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL)); + writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2)); + + /* Digital Video Select : Interlace, clk27 clk, external */ + writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING)); + + /* Reset Video Mode */ + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE)); + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); + + /* Horizontal sync signal output */ + writel_relaxed(mode->hso_begin, + priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN)); + writel_relaxed(mode->hso_end, + priv->io_base + _REG(ENCI_SYNC_HSO_END)); + + /* Vertical Sync lines */ + writel_relaxed(mode->vso_even, + priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN)); + writel_relaxed(mode->vso_odd, + priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN)); + + /* Macrovision max amplitude change */ + writel_relaxed(0x8100 + mode->macv_max_amp, + priv->io_base + _REG(ENCI_MACV_MAX_AMP)); + + /* Video mode */ + writel_relaxed(mode->video_prog_mode, + priv->io_base + _REG(VENC_VIDEO_PROG_MODE)); + writel_relaxed(mode->video_mode, + priv->io_base + _REG(ENCI_VIDEO_MODE)); + + /* Advanced Video Mode : + * Demux shifting 0x2 + * Blank line end at line17/22 + * High bandwidth Luma Filter + * Low bandwidth Chroma Filter + * Bypass luma low pass filter + * No macrovision on CSYNC + */ + writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); + + writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH)); + + /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */ + writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE)); + + /* 0x3 Y, C, and Component Y delay */ + writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY)); + + /* Timings */ + writel_relaxed(mode->pixel_start, + priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START)); + writel_relaxed(mode->pixel_end, + priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END)); + + writel_relaxed(mode->top_field_line_start, + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START)); + writel_relaxed(mode->top_field_line_end, + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END)); + + writel_relaxed(mode->bottom_field_line_start, + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START)); + writel_relaxed(mode->bottom_field_line_end, + priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END)); + + /* Internal Venc, Internal VIU Sync, Internal Vencoder */ + writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE)); + + /* UNreset Interlaced TV Encoder */ + writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST)); + + /* Enable Vfifo2vd, Y_Cb_Y_Cr select */ + writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL)); + + /* Power UP Dacs */ + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING)); + + /* Video Upsampling */ + writel_relaxed(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0)); + writel_relaxed(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1)); + writel_relaxed(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2)); + + /* Select Interlace Y DACs */ + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0)); + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL1)); + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL2)); + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL3)); + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL4)); + writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL5)); + + /* Select ENCI for VIU */ + meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI); + + /* Enable ENCI FIFO */ + writel_relaxed(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL)); + + /* Select ENCI DACs 0, 1, 4, and 5 */ + writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0)); + writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1)); + + /* Interlace video enable */ + writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); + + /* Configure Video Saturation / Contrast / Brightness / Hue */ + writel_relaxed(mode->video_saturation, + priv->io_base + _REG(ENCI_VIDEO_SAT)); + writel_relaxed(mode->video_contrast, + priv->io_base + _REG(ENCI_VIDEO_CONT)); + writel_relaxed(mode->video_brightness, + priv->io_base + _REG(ENCI_VIDEO_BRIGHT)); + writel_relaxed(mode->video_hue, + priv->io_base + _REG(ENCI_VIDEO_HUE)); + + /* Enable DAC0 Filter */ + writel_relaxed(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0)); + writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1)); + + /* 0 in Macrovision register 0 */ + writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0)); + + /* Analog Synchronization and color burst value adjust */ + writel_relaxed(mode->analog_sync_adj, + priv->io_base + _REG(ENCI_SYNC_ADJ)); + + /* Setup 27MHz vclk2 for ENCI and VDAC */ + meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS); + + priv->venc.current_mode = mode->mode_tag; +} + +/* Returns the current ENCI field polarity */ +unsigned int meson_venci_get_field(struct meson_drm *priv) +{ + return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29); +} + +void meson_venc_enable_vsync(struct meson_drm *priv) +{ + writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL)); +} + +void meson_venc_disable_vsync(struct meson_drm *priv) +{ + writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL)); +} + +void meson_venc_init(struct meson_drm *priv) +{ + /* Disable all encoders */ + writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); + writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); + writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN)); + + /* Disable VSync IRQ */ + meson_venc_disable_vsync(priv); + + priv->venc.current_mode = MESON_VENC_MODE_NONE; +} diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h new file mode 100644 index 000000000000..77d4a7d82c44 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_venc.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * Video Encoders + * - ENCI : Interlace Video Encoder + * - ENCI_DVI : Interlace Video Encoder for DVI/HDMI + * - ENCP : Progressive Video Encoder + */ + +#ifndef __MESON_VENC_H +#define __MESON_VENC_H + +enum { + MESON_VENC_MODE_NONE = 0, + MESON_VENC_MODE_CVBS_PAL, + MESON_VENC_MODE_CVBS_NTSC, +}; + +struct meson_cvbs_enci_mode { + unsigned int mode_tag; + unsigned int hso_begin; /* HSO begin position */ + unsigned int hso_end; /* HSO end position */ + unsigned int vso_even; /* VSO even line */ + unsigned int vso_odd; /* VSO odd line */ + unsigned int macv_max_amp; /* Macrovision max amplitude */ + unsigned int video_prog_mode; + unsigned int video_mode; + unsigned int sch_adjust; + unsigned int yc_delay; + unsigned int pixel_start; + unsigned int pixel_end; + unsigned int top_field_line_start; + unsigned int top_field_line_end; + unsigned int bottom_field_line_start; + unsigned int bottom_field_line_end; + unsigned int video_saturation; + unsigned int video_contrast; + unsigned int video_brightness; + unsigned int video_hue; + unsigned int analog_sync_adj; +}; + +/* CVBS Timings and Parameters */ +extern struct meson_cvbs_enci_mode meson_cvbs_enci_pal; +extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc; + +void meson_venci_cvbs_mode_set(struct meson_drm *priv, + struct meson_cvbs_enci_mode *mode); +unsigned int meson_venci_get_field(struct meson_drm *priv); + +void meson_venc_enable_vsync(struct meson_drm *priv); +void meson_venc_disable_vsync(struct meson_drm *priv); + +void meson_venc_init(struct meson_drm *priv); + +#endif /* __MESON_VENC_H */ diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c new file mode 100644 index 000000000000..c809c085fd78 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Written by: + * Jasper St. Pierre + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "meson_venc_cvbs.h" +#include "meson_venc.h" +#include "meson_registers.h" + +/* HHI VDAC Registers */ +#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ +#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ + +struct meson_venc_cvbs { + struct drm_encoder encoder; + struct drm_connector connector; + struct meson_drm *priv; +}; +#define encoder_to_meson_venc_cvbs(x) \ + container_of(x, struct meson_venc_cvbs, encoder) + +#define connector_to_meson_venc_cvbs(x) \ + container_of(x, struct meson_venc_cvbs, connector) + +/* Supported Modes */ + +struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = { + { /* PAL */ + .enci = &meson_cvbs_enci_pal, + .mode = { + DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, + 720, 732, 795, 864, 0, 576, 580, 586, 625, 0, + DRM_MODE_FLAG_INTERLACE), + .vrefresh = 50, + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, + }, + }, + { /* NTSC */ + .enci = &meson_cvbs_enci_ntsc, + .mode = { + DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, + 720, 739, 801, 858, 0, 480, 488, 494, 525, 0, + DRM_MODE_FLAG_INTERLACE), + .vrefresh = 60, + .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, + }, + }, +}; + +/* Connector */ + +static void meson_cvbs_connector_destroy(struct drm_connector *connector) +{ + drm_connector_cleanup(connector); +} + +static enum drm_connector_status +meson_cvbs_connector_detect(struct drm_connector *connector, bool force) +{ + /* FIXME: Add load-detect or jack-detect if possible */ + return connector_status_connected; +} + +static int meson_cvbs_connector_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode; + int i; + + for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) { + struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i]; + + mode = drm_mode_duplicate(dev, &meson_mode->mode); + if (!mode) { + DRM_ERROR("Failed to create a new display mode\n"); + return 0; + } + + drm_mode_probed_add(connector, mode); + } + + return i; +} + +static int meson_cvbs_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + /* Validate the modes added in get_modes */ + return MODE_OK; +} + +static const struct drm_connector_funcs meson_cvbs_connector_funcs = { + .dpms = drm_atomic_helper_connector_dpms, + .detect = meson_cvbs_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = meson_cvbs_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static const +struct drm_connector_helper_funcs meson_cvbs_connector_helper_funcs = { + .get_modes = meson_cvbs_connector_get_modes, + .mode_valid = meson_cvbs_connector_mode_valid, +}; + +/* Encoder */ + +static void meson_venc_cvbs_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs meson_venc_cvbs_encoder_funcs = { + .destroy = meson_venc_cvbs_encoder_destroy, +}; + +static int meson_venc_cvbs_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + int i; + + for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) { + struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i]; + + if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode)) + return 0; + } + + return -EINVAL; +} + +static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder) +{ + struct meson_venc_cvbs *meson_venc_cvbs = + encoder_to_meson_venc_cvbs(encoder); + struct meson_drm *priv = meson_venc_cvbs->priv; + + /* Disable CVBS VDAC */ + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0); + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0); +} + +static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder) +{ + struct meson_venc_cvbs *meson_venc_cvbs = + encoder_to_meson_venc_cvbs(encoder); + struct meson_drm *priv = meson_venc_cvbs->priv; + + /* VDAC0 source is not from ATV */ + writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0)); + + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1); + else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001); + + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0); +} + +static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct meson_venc_cvbs *meson_venc_cvbs = + encoder_to_meson_venc_cvbs(encoder); + int i; + + for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) { + struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i]; + + if (drm_mode_equal(mode, &meson_mode->mode)) { + meson_venci_cvbs_mode_set(meson_venc_cvbs->priv, + meson_mode->enci); + break; + } + } +} + +static const struct drm_encoder_helper_funcs + meson_venc_cvbs_encoder_helper_funcs = { + .atomic_check = meson_venc_cvbs_encoder_atomic_check, + .disable = meson_venc_cvbs_encoder_disable, + .enable = meson_venc_cvbs_encoder_enable, + .mode_set = meson_venc_cvbs_encoder_mode_set, +}; + +static bool meson_venc_cvbs_connector_is_available(struct meson_drm *priv) +{ + struct device_node *ep, *remote; + + /* CVBS VDAC output is on the first port, first endpoint */ + ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0); + if (!ep) + return false; + + + /* If the endpoint node exists, consider it enabled */ + remote = of_graph_get_remote_port(ep); + if (remote) { + of_node_put(ep); + return true; + } + + of_node_put(ep); + of_node_put(remote); + + return false; +} + +int meson_venc_cvbs_create(struct meson_drm *priv) +{ + struct drm_device *drm = priv->drm; + struct meson_venc_cvbs *meson_venc_cvbs; + struct drm_connector *connector; + struct drm_encoder *encoder; + int ret; + + if (!meson_venc_cvbs_connector_is_available(priv)) { + dev_info(drm->dev, "CVBS Output connector not available\n"); + return -ENODEV; + } + + meson_venc_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_venc_cvbs), + GFP_KERNEL); + if (!meson_venc_cvbs) + return -ENOMEM; + + meson_venc_cvbs->priv = priv; + encoder = &meson_venc_cvbs->encoder; + connector = &meson_venc_cvbs->connector; + + /* Connector */ + + drm_connector_helper_add(connector, + &meson_cvbs_connector_helper_funcs); + + ret = drm_connector_init(drm, connector, &meson_cvbs_connector_funcs, + DRM_MODE_CONNECTOR_Composite); + if (ret) { + dev_err(priv->dev, "Failed to init CVBS connector\n"); + return ret; + } + + connector->interlace_allowed = 1; + + /* Encoder */ + + drm_encoder_helper_add(encoder, &meson_venc_cvbs_encoder_helper_funcs); + + ret = drm_encoder_init(drm, encoder, &meson_venc_cvbs_encoder_funcs, + DRM_MODE_ENCODER_TVDAC, "meson_venc_cvbs"); + if (ret) { + dev_err(priv->dev, "Failed to init CVBS encoder\n"); + return ret; + } + + encoder->possible_crtcs = BIT(0); + + drm_mode_connector_attach_encoder(connector, encoder); + + return 0; +} diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.h b/drivers/gpu/drm/meson/meson_venc_cvbs.h new file mode 100644 index 000000000000..9256ccf9d931 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_venc_cvbs.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Written by: + * Jasper St. Pierre + */ + +#ifndef __MESON_VENC_CVBS_H +#define __MESON_VENC_CVBS_H + +#include "meson_drv.h" +#include "meson_venc.h" + +struct meson_cvbs_mode { + struct meson_cvbs_enci_mode *enci; + struct drm_display_mode mode; +}; + +#define MESON_CVBS_MODES_COUNT 2 + +/* Modes supported by the CVBS output */ +extern struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT]; + +int meson_venc_cvbs_create(struct meson_drm *priv); + +#endif /* __MESON_VENC_CVBS_H */ diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c new file mode 100644 index 000000000000..a6de8ba7af19 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_viu.c @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include "meson_drv.h" +#include "meson_viu.h" +#include "meson_vpp.h" +#include "meson_venc.h" +#include "meson_canvas.h" +#include "meson_registers.h" + +/* + * VIU Handles the Pixel scanout and the basic Colorspace conversions + * We handle the following features : + * - OSD1 RGB565/RGB888/xRGB8888 scanout + * - RGB conversion to x/cb/cr + * - Progressive or Interlace buffer scanout + * - OSD1 Commit on Vsync + * - HDR OSD matrix for GXL/GXM + * + * What is missing : + * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes + * - YUV4:2:2 Y0CbY1Cr scanout + * - Conversion to YUV 4:4:4 from 4:2:2 input + * - Colorkey Alpha matching + * - Big endian scanout + * - X/Y reverse scanout + * - Global alpha setup + * - OSD2 support, would need interlace switching on vsync + * - OSD1 full scaling to support TV overscan + */ + +/* OSD csc defines */ + +enum viu_matrix_sel_e { + VIU_MATRIX_OSD_EOTF = 0, + VIU_MATRIX_OSD, +}; + +enum viu_lut_sel_e { + VIU_LUT_OSD_EOTF = 0, + VIU_LUT_OSD_OETF, +}; + +#define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2)) +#define MATRIX_5X3_COEF_SIZE 24 + +#define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2)) +#define EOTF_COEFF_SIZE 10 +#define EOTF_COEFF_RIGHTSHIFT 1 + +static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = { + 0, 0, 0, /* pre offset */ + COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765), + COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500), + COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116), + 0, 0, 0, /* 10'/11'/12' */ + 0, 0, 0, /* 20'/21'/22' */ + 64, 512, 512, /* offset */ + 0, 0, 0 /* mode, right_shift, clip_en */ +}; + +/* eotf matrix: bypass */ +static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = { + EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), + EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), + EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), + EOTF_COEFF_RIGHTSHIFT /* right shift */ +}; + +void meson_viu_set_osd_matrix(struct meson_drm *priv, + enum viu_matrix_sel_e m_select, + int *m, bool csc_on) +{ + if (m_select == VIU_MATRIX_OSD) { + /* osd matrix, VIU_MATRIX_0 */ + writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff), + priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1)); + writel(m[2] & 0xfff, + priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2)); + writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff), + priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01)); + writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff), + priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10)); + writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff), + priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12)); + writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff), + priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21)); + + if (m[21]) { + writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff), + priv->io_base + + _REG(VIU_OSD1_MATRIX_COEF22_30)); + writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff), + priv->io_base + + _REG(VIU_OSD1_MATRIX_COEF31_32)); + writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff), + priv->io_base + + _REG(VIU_OSD1_MATRIX_COEF40_41)); + writel(m[17] & 0x1fff, priv->io_base + + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); + } else + writel((m[11] & 0x1fff) << 16, priv->io_base + + _REG(VIU_OSD1_MATRIX_COEF22_30)); + + writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff), + priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1)); + writel(m[20] & 0xfff, + priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2)); + + writel_bits_relaxed(3 << 30, m[21] << 30, + priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); + writel_bits_relaxed(7 << 16, m[22] << 16, + priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42)); + + /* 23 reserved for clipping control */ + writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0, + priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL)); + writel_bits_relaxed(BIT(1), 0, + priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL)); + } else if (m_select == VIU_MATRIX_OSD_EOTF) { + int i; + + /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */ + for (i = 0; i < 5; i++) + writel(((m[i * 2] & 0x1fff) << 16) | + (m[i * 2 + 1] & 0x1fff), priv->io_base + + _REG(VIU_OSD1_EOTF_CTL + i + 1)); + + writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0, + priv->io_base + _REG(VIU_OSD1_EOTF_CTL)); + writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0, + priv->io_base + _REG(VIU_OSD1_EOTF_CTL)); + } +} + +#define OSD_EOTF_LUT_SIZE 33 +#define OSD_OETF_LUT_SIZE 41 + +void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel, + unsigned int *r_map, unsigned int *g_map, + unsigned int *b_map, + bool csc_on) +{ + unsigned int addr_port; + unsigned int data_port; + unsigned int ctrl_port; + int i; + + if (lut_sel == VIU_LUT_OSD_EOTF) { + addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT; + data_port = VIU_OSD1_EOTF_LUT_DATA_PORT; + ctrl_port = VIU_OSD1_EOTF_CTL; + } else if (lut_sel == VIU_LUT_OSD_OETF) { + addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT; + data_port = VIU_OSD1_OETF_LUT_DATA_PORT; + ctrl_port = VIU_OSD1_OETF_CTL; + } else + return; + + if (lut_sel == VIU_LUT_OSD_OETF) { + writel(0, priv->io_base + _REG(addr_port)); + + for (i = 0; i < 20; i++) + writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), + priv->io_base + _REG(data_port)); + + writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16), + priv->io_base + _REG(data_port)); + + for (i = 0; i < 20; i++) + writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), + priv->io_base + _REG(data_port)); + + for (i = 0; i < 20; i++) + writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), + priv->io_base + _REG(data_port)); + + writel(b_map[OSD_OETF_LUT_SIZE - 1], + priv->io_base + _REG(data_port)); + + if (csc_on) + writel_bits_relaxed(0x7 << 29, 7 << 29, + priv->io_base + _REG(ctrl_port)); + else + writel_bits_relaxed(0x7 << 29, 0, + priv->io_base + _REG(ctrl_port)); + } else if (lut_sel == VIU_LUT_OSD_EOTF) { + writel(0, priv->io_base + _REG(addr_port)); + + for (i = 0; i < 20; i++) + writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), + priv->io_base + _REG(data_port)); + + writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16), + priv->io_base + _REG(data_port)); + + for (i = 0; i < 20; i++) + writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), + priv->io_base + _REG(data_port)); + + for (i = 0; i < 20; i++) + writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), + priv->io_base + _REG(data_port)); + + writel(b_map[OSD_EOTF_LUT_SIZE - 1], + priv->io_base + _REG(data_port)); + + if (csc_on) + writel_bits_relaxed(7 << 27, 7 << 27, + priv->io_base + _REG(ctrl_port)); + else + writel_bits_relaxed(7 << 27, 0, + priv->io_base + _REG(ctrl_port)); + + writel_bits_relaxed(BIT(31), BIT(31), + priv->io_base + _REG(ctrl_port)); + } +} + +/* eotf lut: linear */ +static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = { + 0x0000, 0x0200, 0x0400, 0x0600, + 0x0800, 0x0a00, 0x0c00, 0x0e00, + 0x1000, 0x1200, 0x1400, 0x1600, + 0x1800, 0x1a00, 0x1c00, 0x1e00, + 0x2000, 0x2200, 0x2400, 0x2600, + 0x2800, 0x2a00, 0x2c00, 0x2e00, + 0x3000, 0x3200, 0x3400, 0x3600, + 0x3800, 0x3a00, 0x3c00, 0x3e00, + 0x4000 +}; + +/* osd oetf lut: linear */ +static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = { + 0, 0, 0, 0, + 0, 32, 64, 96, + 128, 160, 196, 224, + 256, 288, 320, 352, + 384, 416, 448, 480, + 512, 544, 576, 608, + 640, 672, 704, 736, + 768, 800, 832, 864, + 896, 928, 960, 992, + 1023, 1023, 1023, 1023, + 1023 +}; + +static void meson_viu_load_matrix(struct meson_drm *priv) +{ + /* eotf lut bypass */ + meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF, + eotf_33_linear_mapping, /* R */ + eotf_33_linear_mapping, /* G */ + eotf_33_linear_mapping, /* B */ + false); + + /* eotf matrix bypass */ + meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF, + eotf_bypass_coeff, + false); + + /* oetf lut bypass */ + meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF, + oetf_41_linear_mapping, /* R */ + oetf_41_linear_mapping, /* G */ + oetf_41_linear_mapping, /* B */ + false); + + /* osd matrix RGB709 to YUV709 limit */ + meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD, + RGB709_to_YUV709l_coeff, + true); +} + +void meson_viu_init(struct meson_drm *priv) +{ + uint32_t reg; + + /* Disable OSDs */ + writel_bits_relaxed(BIT(0) | BIT(21), 0, + priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); + writel_bits_relaxed(BIT(0) | BIT(21), 0, + priv->io_base + _REG(VIU_OSD2_CTRL_STAT)); + + /* On GXL/GXM, Use the 10bit HDR conversion matrix */ + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) + meson_viu_load_matrix(priv); + + /* Initialize OSD1 fifo control register */ + reg = BIT(0) | /* Urgent DDR request priority */ + (4 << 5) | /* hold_fifo_lines */ + (3 << 10) | /* burst length 64 */ + (32 << 12) | /* fifo_depth_val: 32*8=256 */ + (2 << 22) | /* 4 words in 1 burst */ + (2 << 24); + writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); + writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); + + /* Set OSD alpha replace value */ + writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT, + 0xff << OSD_REPLACE_SHIFT, + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); + writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT, + 0xff << OSD_REPLACE_SHIFT, + priv->io_base + _REG(VIU_OSD2_CTRL_STAT2)); + + priv->viu.osd1_enabled = false; + priv->viu.osd1_commit = false; + priv->viu.osd1_interlace = false; +} diff --git a/drivers/gpu/drm/meson/meson_viu.h b/drivers/gpu/drm/meson/meson_viu.h new file mode 100644 index 000000000000..073b1910bd1b --- /dev/null +++ b/drivers/gpu/drm/meson/meson_viu.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* Video Input Unit */ + +#ifndef __MESON_VIU_H +#define __MESON_VIU_H + +/* OSDx_BLKx_CFG */ +#define OSD_CANVAS_SEL 16 + +#define OSD_ENDIANNESS_LE BIT(15) +#define OSD_ENDIANNESS_BE (0) + +#define OSD_BLK_MODE_422 (0x03 << 8) +#define OSD_BLK_MODE_16 (0x04 << 8) +#define OSD_BLK_MODE_32 (0x05 << 8) +#define OSD_BLK_MODE_24 (0x07 << 8) + +#define OSD_OUTPUT_COLOR_RGB BIT(7) +#define OSD_OUTPUT_COLOR_YUV (0) + +#define OSD_COLOR_MATRIX_32_RGBA (0x00 << 2) +#define OSD_COLOR_MATRIX_32_ARGB (0x01 << 2) +#define OSD_COLOR_MATRIX_32_ABGR (0x02 << 2) +#define OSD_COLOR_MATRIX_32_BGRA (0x03 << 2) + +#define OSD_COLOR_MATRIX_24_RGB (0x00 << 2) + +#define OSD_COLOR_MATRIX_16_RGB655 (0x00 << 2) +#define OSD_COLOR_MATRIX_16_RGB565 (0x04 << 2) + +#define OSD_INTERLACE_ENABLED BIT(1) +#define OSD_INTERLACE_ODD BIT(0) +#define OSD_INTERLACE_EVEN (0) + +/* OSDx_CTRL_STAT */ +#define OSD_ENABLE BIT(21) +#define OSD_BLK0_ENABLE BIT(0) + +#define OSD_GLOBAL_ALPHA_SHIFT 12 + +/* OSDx_CTRL_STAT2 */ +#define OSD_REPLACE_EN BIT(14) +#define OSD_REPLACE_SHIFT 6 + +void meson_viu_init(struct meson_drm *priv); + +#endif /* __MESON_VIU_H */ diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c new file mode 100644 index 000000000000..671909d8672e --- /dev/null +++ b/drivers/gpu/drm/meson/meson_vpp.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * Copyright (C) 2014 Endless Mobile + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include "meson_drv.h" +#include "meson_vpp.h" +#include "meson_registers.h" + +/* + * VPP Handles all the Post Processing after the Scanout from the VIU + * We handle the following post processings : + * - Postblend : Blends the OSD1 only + * We exclude OSD2, VS1, VS1 and Preblend output + * - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and + * use it only for interlace scanout + * - Intermediate FIFO with default Amlogic values + * + * What is missing : + * - Preblend for video overlay pre-scaling + * - OSD2 support for cursor framebuffer + * - Video pre-scaling before postblend + * - Full Vertical/Horizontal OSD scaling to support TV overscan + * - HDR conversion + */ + +void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux) +{ + writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL)); +} + +/* + * When the output is interlaced, the OSD must switch between + * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0 + * at each vsync. + * But the vertical scaler can provide such funtionnality if + * is configured for 2:1 scaling with interlace options enabled. + */ +void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv, + struct drm_rect *input) +{ + writel_relaxed(BIT(3) /* Enable scaler */ | + BIT(2), /* Select OSD1 */ + priv->io_base + _REG(VPP_OSD_SC_CTRL0)); + + writel_relaxed(((drm_rect_width(input) - 1) << 16) | + (drm_rect_height(input) - 1), + priv->io_base + _REG(VPP_OSD_SCI_WH_M1)); + /* 2:1 scaling */ + writel_relaxed(((input->x1) << 16) | (input->x2), + priv->io_base + _REG(VPP_OSD_SCO_H_START_END)); + writel_relaxed(((input->y1 >> 1) << 16) | (input->y2 >> 1), + priv->io_base + _REG(VPP_OSD_SCO_V_START_END)); + + /* 2:1 scaling values */ + writel_relaxed(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE)); + writel_relaxed(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP)); + + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0)); + + writel_relaxed((4 << 0) /* osd_vsc_bank_length */ | + (4 << 3) /* osd_vsc_top_ini_rcv_num0 */ | + (1 << 8) /* osd_vsc_top_rpt_p0_num0 */ | + (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ | + (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ | + BIT(23) /* osd_prog_interlace */ | + BIT(24), /* Enable vertical scaler */ + priv->io_base + _REG(VPP_OSD_VSC_CTRL0)); +} + +void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv) +{ + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0)); + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0)); + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0)); +} + +static unsigned int vpp_filter_coefs_4point_bspline[] = { + 0x15561500, 0x14561600, 0x13561700, 0x12561800, + 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00, + 0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200, + 0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700, + 0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01, + 0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201, + 0x05473301, 0x05463401, 0x04453601, 0x04433702, + 0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02, + 0x033d3d03 +}; + +static void meson_vpp_write_scaling_filter_coefs(struct meson_drm *priv, + const unsigned int *coefs, + bool is_horizontal) +{ + int i; + + writel_relaxed(is_horizontal ? BIT(8) : 0, + priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX)); + for (i = 0; i < 33; i++) + writel_relaxed(coefs[i], + priv->io_base + _REG(VPP_OSD_SCALE_COEF)); +} + +void meson_vpp_init(struct meson_drm *priv) +{ + /* set dummy data default YUV black */ + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) + writel_relaxed(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1)); + else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu")) { + writel_bits_relaxed(0xff << 16, 0xff << 16, + priv->io_base + _REG(VIU_MISC_CTRL1)); + writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL)); + writel_relaxed(0x1020080, + priv->io_base + _REG(VPP_DUMMY_DATA1)); + } + + /* Initialize vpu fifo control registers */ + writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) | + 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE)); + writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES)); + + /* Turn off preblend */ + writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0, + priv->io_base + _REG(VPP_MISC)); + + /* Turn off POSTBLEND */ + writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0, + priv->io_base + _REG(VPP_MISC)); + + /* Force all planes off */ + writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND | + VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND, 0, + priv->io_base + _REG(VPP_MISC)); + + /* Disable Scalers */ + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0)); + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0)); + writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0)); + + /* Write in the proper filter coefficients. */ + meson_vpp_write_scaling_filter_coefs(priv, + vpp_filter_coefs_4point_bspline, false); + meson_vpp_write_scaling_filter_coefs(priv, + vpp_filter_coefs_4point_bspline, true); +} diff --git a/drivers/gpu/drm/meson/meson_vpp.h b/drivers/gpu/drm/meson/meson_vpp.h new file mode 100644 index 000000000000..ede3b26e0f22 --- /dev/null +++ b/drivers/gpu/drm/meson/meson_vpp.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 BayLibre, SAS + * Author: Neil Armstrong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* Video Post Process */ + +#ifndef __MESON_VPP_H +#define __MESON_VPP_H + +/* Mux VIU/VPP to ENCI */ +#define MESON_VIU_VPP_MUX_ENCI 0x5 + +void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux); + +void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv, + struct drm_rect *input); +void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv); + +void meson_vpp_init(struct meson_drm *priv); + +#endif /* __MESON_VPP_H */ From ce1135c7de646bd608784657471b934d6e50195d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 22 Nov 2016 14:41:20 +0000 Subject: [PATCH 024/104] drm/i915: Complete requests in nop_submit_request Since the submit/execute split in commit d55ac5bf97c6 ("drm/i915: Defer transfer onto execution timeline to actual hw submission") the global seqno advance was deferred until the submit_request callback. After wedging the GPU, we were installing a nop_submit_request handler (to avoid waking up the dead hw) but I had missed converting this over to the new scheme. Under the new scheme, we have to explicitly call i915_gem_submit_request() from the submit_request handler to mark the request as on the hardware. If we don't the request is always pending, and any waiter will continue to wait indefinitely and hangcheck will not be able to resolve the lockup. References: https://bugs.freedesktop.org/show_bug.cgi?id=98748 Testcase: igt/gem_eio/in-flight Fixes: d55ac5bf97c6 ("drm/i915: Defer transfer onto execution timeline to actual hw submission") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161122144121.7379-3-chris@chris-wilson.co.uk (cherry picked from commit 3dcf93f7f23a61e867a5ccadaf651cb2d29229fd) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 902fa427c196..d0dcaf35b429 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2764,6 +2764,8 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) static void nop_submit_request(struct drm_i915_gem_request *request) { + i915_gem_request_submit(request); + intel_engine_init_global_seqno(request->engine, request->global_seqno); } static void i915_gem_cleanup_engine(struct intel_engine_cs *engine) From 991015743272cd2836b1d1b94b6894e2269e241f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 22 Nov 2016 22:21:53 +0200 Subject: [PATCH 025/104] drm/i915: Make skl_write_{plane,cursor}_wm() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Someone forgot to make skl_write_{plane,cursor}_wm() static when removing the prototypes from the header. Sparse isn't pleased. Cc: Maarten Lankhorst Cc: Lyude Cc: Matt Roper Fixes: e62929b3f628 ("drm/i915/gen9+: Program watermarks as a separate step during evasion, v3.") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1479846113-24745-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Lyude Reviewed-by: Maarten Lankhorst (cherry picked from commit d9348dec902ff36e0f1b25ccf1f4be25fc1ac409) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_pm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e207dc69e8b3..cbd0f3269b2d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3851,10 +3851,10 @@ static void skl_write_wm_level(struct drm_i915_private *dev_priv, I915_WRITE(reg, val); } -void skl_write_plane_wm(struct intel_crtc *intel_crtc, - const struct skl_plane_wm *wm, - const struct skl_ddb_allocation *ddb, - int plane) +static void skl_write_plane_wm(struct intel_crtc *intel_crtc, + const struct skl_plane_wm *wm, + const struct skl_ddb_allocation *ddb, + int plane) { struct drm_crtc *crtc = &intel_crtc->base; struct drm_device *dev = crtc->dev; @@ -3875,9 +3875,9 @@ void skl_write_plane_wm(struct intel_crtc *intel_crtc, &ddb->y_plane[pipe][plane]); } -void skl_write_cursor_wm(struct intel_crtc *intel_crtc, - const struct skl_plane_wm *wm, - const struct skl_ddb_allocation *ddb) +static void skl_write_cursor_wm(struct intel_crtc *intel_crtc, + const struct skl_plane_wm *wm, + const struct skl_ddb_allocation *ddb) { struct drm_crtc *crtc = &intel_crtc->base; struct drm_device *dev = crtc->dev; From 14676ec6b1a6f2f7fa0bafd98ab42ce77be7a7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Nov 2016 18:35:09 +0200 Subject: [PATCH 026/104] drm/i915: Fix cdclk vs. dev_cdclk mess when not recomputing things MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we end up not recomputing the cdclk, we need to populate intel_state->cdclk with the "atomic_cdclk_freq" instead of the current cdclk_freq. When no pipes are active, the actual cdclk_freq may be lower than what the configuration of the planes and pipes would require from the point of view of the software state. This fixes bogus WARNS from skl_max_scale() which is trying to check the plane software state against the cdclk frequency. So any time it got called during DPMS off for instance, we might have tripped the warn if the current mode would have required a higher than minimum cdclk. v2: Drop the dev_cdclk stuff (Maarten) Cc: Maarten Lankhorst Cc: Mika Kahola Cc: bruno.pagani@ens-lyon.org Cc: Daniel J Blueman Cc: Paul Bolle Cc: Joseph Yasi Tested-by: Paul Bolle Tested-by: Joseph Yasi (v1) Cc: # v4.6+ Fixes: 1a617b77658e ("drm/i915: Keep track of the cdclk as if all crtc's were active.") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98214 Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1479141311-11904-2-git-send-email-ville.syrjala@linux.intel.com (cherry picked from commit e0ca7a6be38ce603d26df5707c22e53870a623e0) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8d270f7650de..7b5add5e9fd9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13994,8 +13994,9 @@ static int intel_modeset_checks(struct drm_atomic_state *state) DRM_DEBUG_KMS("New cdclk calculated to be atomic %u, actual %u\n", intel_state->cdclk, intel_state->dev_cdclk); - } else + } else { to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq; + } intel_modeset_clear_plls(state); @@ -14096,8 +14097,9 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; - } else - intel_state->cdclk = dev_priv->cdclk_freq; + } else { + intel_state->cdclk = dev_priv->atomic_cdclk_freq; + } ret = drm_atomic_helper_check_planes(dev, state); if (ret) From 1f3dc3e334c1192ebe2939ea17ba12f4776f90c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 29 Nov 2016 16:13:57 +0200 Subject: [PATCH 027/104] drm/i915: Initialize dev_priv->atomic_cdclk_freq at init time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like we're only initializing dev_priv->atomic_cdclk_freq at resume and commit times, not at init time. Let's do that as well. We're now hitting the 'WARN_ON(intel_state->cdclk == 0)' in hsw_compute_linetime_wm() on account of populating intel_state->cdclk from dev_priv->atomic_cdclk_freq. Previously we were mispopulating intel_state->cdclk with dev_priv->cdclk_freq which always had a proper value at init time and hence the WARN_ON() didn't trigger. Cc: # 4.6+: 14676ec6b1a6 drm/i915: Fix cdclk vs. dev_cdclk mess when not recomputing things Cc: # 4.6+ Cc: Matthew Auld Reported-by: Matthew Auld Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98902 Fixes: 14676ec6b1a6 ("drm/i915: Fix cdclk vs. dev_cdclk mess when not recomputing things") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1480428837-4207-1-git-send-email-ville.syrjala@linux.intel.com Tested-by: Matthew Auld Reviewed-by: Matthew Auld (cherry picked from commit 6a259b1f8a9e99b1ed114f8bf8b0cfccee130e54) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7b5add5e9fd9..5ebfe0778c53 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -16486,6 +16486,7 @@ int intel_modeset_init(struct drm_device *dev) intel_update_czclk(dev_priv); intel_update_cdclk(dev_priv); + dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; intel_shared_dpll_init(dev); From 6cef2f8477206fc0a6961358e8ef9d01a3201a5c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 24 Nov 2016 09:34:01 +0000 Subject: [PATCH 028/104] drm/i915/debugfs: Drop i915_hws_info i915_hws_info() has not been kept upto date (missing new engines) and so I consider it to be unused. HWS is included in the error state, which would be an avenue to retrieving it if required in future (possibly via i915_engine_info). As it is currently oopsing with an rpm testcase, just remove it. Fixes: 3b3f1650b1ca ("drm/i915: Allocate intel_engine_cs structure only for the enabled engines") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98838 Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161124093401.18852-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin (cherry picked from commit 30576a2c462d9658508c3de67601aa565f973064) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_debugfs.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 96407f684f7f..673fcba26fe2 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -935,27 +935,6 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data) return 0; } -static int i915_hws_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = m->private; - struct drm_i915_private *dev_priv = node_to_i915(node); - struct intel_engine_cs *engine; - const u32 *hws; - int i; - - engine = dev_priv->engine[(uintptr_t)node->info_ent->data]; - hws = engine->status_page.page_addr; - if (hws == NULL) - return 0; - - for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) { - seq_printf(m, "0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", - i * 4, - hws[i], hws[i + 1], hws[i + 2], hws[i + 3]); - } - return 0; -} - #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) static ssize_t @@ -5403,10 +5382,6 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_seqno", i915_gem_seqno_info, 0}, {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, {"i915_gem_interrupt", i915_interrupt_info, 0}, - {"i915_gem_hws", i915_hws_info, 0, (void *)RCS}, - {"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS}, - {"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS}, - {"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS}, {"i915_gem_batch_pool", i915_gem_batch_pool_info, 0}, {"i915_guc_info", i915_guc_info, 0}, {"i915_guc_load_status", i915_guc_load_status_info, 0}, From 3acd24017563e1ce333eb52d37b7e69480cd4100 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 24 Nov 2016 09:47:52 +0000 Subject: [PATCH 029/104] drm/i915/debugfs: Increment return value of gt.next_seqno The i915_next_seqno read value is to be the next seqno used by the kernel. However, in the conversion to atomics ops for gt.next_seqno, in commit 28176ef4cfa5 ("drm/i915: Reserve space in the global seqno during request allocation"), this was changed from a post-increment to a pre-increment. This increment was missed from the value reported by debugfs, so in effect it was reporting the current seqno (last assigned), not the next seqno. Fixes: 28176ef4cfa5 ("drm/i915: Reserve space in the global seqno during request allocation") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=81209 Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161124094752.19129-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen (cherry picked from commit 9607ae79710afb453173b90d5bf564788a6e09b1) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 673fcba26fe2..7dcdf04a8b2b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1026,7 +1026,7 @@ i915_next_seqno_get(void *data, u64 *val) { struct drm_i915_private *dev_priv = data; - *val = atomic_read(&dev_priv->gt.global_timeline.next_seqno); + *val = 1 + atomic_read(&dev_priv->gt.global_timeline.next_seqno); return 0; } From b9f16ff2730c1be06ca89518d5c369b12ffbbc6c Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Fri, 11 Nov 2016 16:46:28 +0800 Subject: [PATCH 030/104] drm/i915/audio: fix hdmi audio noise issue Some monitors will have noise or even no sound after applying the patch 6014ac12. In patch 6014ac12, it will reset the cts value to 0 for HDMI. However, we need to disable Enable CTS or M Prog bit. This is the initial setting after HW reset. Fixes: 6014ac122ed0 ("drm/i915/audio: set proper N/M in modeset") Signed-off-by: Libin Yang Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1478853988-139842-1-git-send-email-libin.yang@intel.com (cherry picked from commit 60abfbb86a8d51576f90c5adcbb4f547a2952782) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_audio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 1c509f7410f5..49f10538d4aa 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -351,10 +351,13 @@ hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, I915_WRITE(HSW_AUD_CFG(pipe), tmp); + /* + * Let's disable "Enable CTS or M Prog bit" + * and let HW calculate the value + */ tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe)); - tmp &= ~AUD_CONFIG_M_MASK; + tmp &= ~AUD_M_CTS_M_PROG_ENABLE; tmp &= ~AUD_M_CTS_M_VALUE_INDEX; - tmp |= AUD_M_CTS_M_PROG_ENABLE; I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp); } From 0e932c080cdee38e873476df92d7dc02bdb023bc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 25 Nov 2016 13:17:17 +0000 Subject: [PATCH 031/104] drm/i915: Hold a reference on the request for its fence chain Currently, we have an active reference for the request until it is retired. Though it cannot be retired before it has been executed by hardware, the request may be completed before we have finished processing the execute fence, i.e. we may continue to process that fence as we free the request. Fixes: 5590af3e115a ("drm/i915: Drive request submission through fence callbacks") Fixes: 23902e49c999 ("drm/i915: Split request submit/execute phase into two") Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20161125131718.20978-3-chris@chris-wilson.co.uk (cherry picked from commit 48bc2a4a427ad81578f887d71d45794619a77211) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem_request.c | 34 ++++++++++++++++++++----- drivers/gpu/drm/i915/i915_sw_fence.h | 5 ++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 27e8f257fb39..57194471f8cd 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -200,8 +200,8 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) struct i915_gem_active *active, *next; lockdep_assert_held(&request->i915->drm.struct_mutex); - GEM_BUG_ON(!i915_sw_fence_done(&request->submit)); - GEM_BUG_ON(!i915_sw_fence_done(&request->execute)); + GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit)); + GEM_BUG_ON(!i915_sw_fence_signaled(&request->execute)); GEM_BUG_ON(!i915_gem_request_completed(request)); GEM_BUG_ON(!request->i915->gt.active_requests); @@ -445,11 +445,17 @@ void i915_gem_request_submit(struct drm_i915_gem_request *request) static int __i915_sw_fence_call submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { - if (state == FENCE_COMPLETE) { - struct drm_i915_gem_request *request = - container_of(fence, typeof(*request), submit); + struct drm_i915_gem_request *request = + container_of(fence, typeof(*request), submit); + switch (state) { + case FENCE_COMPLETE: request->engine->submit_request(request); + break; + + case FENCE_FREE: + i915_gem_request_put(request); + break; } return NOTIFY_DONE; @@ -458,6 +464,18 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) static int __i915_sw_fence_call execute_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { + struct drm_i915_gem_request *request = + container_of(fence, typeof(*request), execute); + + switch (state) { + case FENCE_COMPLETE: + break; + + case FENCE_FREE: + i915_gem_request_put(request); + break; + } + return NOTIFY_DONE; } @@ -545,8 +563,10 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, req->timeline->fence_context, __timeline_get_seqno(req->timeline->common)); - i915_sw_fence_init(&req->submit, submit_notify); - i915_sw_fence_init(&req->execute, execute_notify); + /* We bump the ref for the fence chain */ + i915_sw_fence_init(&i915_gem_request_get(req)->submit, submit_notify); + i915_sw_fence_init(&i915_gem_request_get(req)->execute, execute_notify); + /* Ensure that the execute fence completes after the submit fence - * as we complete the execute fence from within the submit fence * callback, its completion would otherwise be visible first. diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index 7508d23f823b..0f3185ef7f4e 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -75,6 +75,11 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, unsigned long timeout, gfp_t gfp); +static inline bool i915_sw_fence_signaled(const struct i915_sw_fence *fence) +{ + return atomic_read(&fence->pending) <= 0; +} + static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence) { return atomic_read(&fence->pending) < 0; From 7a9e10253e9e52451bbe80ddb2874368dbd240a3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 28 Nov 2016 14:36:48 +0000 Subject: [PATCH 032/104] drm/i915: Move priority bumping for flips earlier David found another issue with priority bumping from mmioflips, where we are accessing the requests concurrently to them being retired and freed. Whilst we are skipping the dependency if has been submitted, that is not sufficient to stop the dependency from disappearing if another thread retires that request. To prevent we can either employ the struct_mutex (or a request mutex in the future) to serialise retiring before it is freed. Alternatively, we need to keep the dependencies alive using RCU whilst they are being accessed via the DFS. [ 1746.698111] general protection fault: 0000 [#1] PREEMPT SMP [ 1746.698305] Modules linked in: snd_hda_intel snd_hda_codec snd_hwdep x86_pkg_temp_thermal snd_hda_core coretemp crct10dif_pclmul crc32_pclmul snd_pcm ghash_clmulni_intel mei_me mei i915 e1000e ptp pps_core i2c_hid [ 1746.698750] CPU: 1 PID: 6716 Comm: kworker/u8:2 Not tainted 4.9.0-rc6-CI-Nightly_816+ #1 [ 1746.698871] Hardware name: GIGABYTE GB-BKi7A-7500/MFLP7AP-00, BIOS F1 07/27/2016 [ 1746.699125] Workqueue: events_unbound intel_mmio_flip_work_func [i915] [ 1746.699266] task: ffff880260a5e800 task.stack: ffffc90000f6c000 [ 1746.699361] RIP: 0010:[] [] execlists_schedule+0x8d/0x300 [i915] [ 1746.699632] RSP: 0018:ffffc90000f6fcd8 EFLAGS: 00010206 [ 1746.699724] RAX: dead0000000000f8 RBX: ffff8801f64b2bf0 RCX: ffff8801f64b2c10 [ 1746.699842] RDX: dead000000000100 RSI: 0000000000000000 RDI: ffff8801f64b0458 [ 1746.699972] RBP: ffffc90000f6fd68 R08: ffff88026488dc00 R09: 0000000000000002 [ 1746.700090] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000400 [ 1746.700195] R13: ffffc90000f6fcf0 R14: ffff88020955aa40 R15: ffff88020955aa68 [ 1746.700307] FS: 0000000000000000(0000) GS:ffff88026dc80000(0000) knlGS:0000000000000000 [ 1746.700435] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1746.700532] CR2: 0000000002a69e90 CR3: 0000000002c07000 CR4: 00000000003406e0 [ 1746.700635] Stack: [ 1746.700682] ffff880260a5e880 ffffc90000f6fd50 ffffffff810af69a ffffc90000f6fd28 [ 1746.700827] ffff88020955a628 ffff8801e1eaebf0 0000000000000020 0000000000000000 [ 1746.700947] 00000196af1edc96 ffff88025dfa4000 ffff8801f0b030a8 ffffc90000f6fcf0 [ 1746.701071] Call Trace: [ 1746.701117] [] ? dequeue_entity+0x25a/0xb50 [ 1746.701260] [] fence_set_priority+0x7e/0x80 [i915] [ 1746.701406] [] i915_gem_object_wait_priority+0x85/0x160 [i915] [ 1746.701599] [] intel_mmio_flip_work_func+0x47/0x2b0 [i915] [ 1746.701717] [] process_one_work+0x14d/0x470 [ 1746.701809] [] worker_thread+0x43/0x4e0 [ 1746.701888] [] ? process_one_work+0x470/0x470 [ 1746.701969] [] ? process_one_work+0x470/0x470 [ 1746.702072] [] kthread+0xc5/0xe0 [ 1746.702152] [] ? _raw_spin_unlock_irq+0x9/0x10 [ 1746.702234] [] ? kthread_park+0x60/0x60 [ 1746.702318] [] ret_from_fork+0x22/0x30 [ 1746.702387] Code: 89 42 08 48 8b 45 88 48 89 55 c0 4c 89 6d c8 4c 8d 70 d8 4d 8d 7e 28 4d 39 ef 74 72 49 8b 1e 48 8b 13 48 39 d3 48 8d 42 f8 74 3e <48> 8b 10 8b 52 38 41 39 d4 7e 26 48 8b 50 30 48 8b 78 28 48 8d [ 1746.702921] RIP [] execlists_schedule+0x8d/0x300 [i915] Nov 25 21:42:54 kbl-gbbki7 kernel: [ 1746.703027] RSP Fixes: 27745e829a5c ("drm/i915/execlists: Use a local lock for dfs_link access") Fixes: 9a151987d709 ("drm/i915: Add execution priority boosting for mmioflips") Signed-off-by: Chris Wilson Cc: David Weinehall Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/20161128143649.4289-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin (cherry picked from commit 92117f0bce64268b841261774e45462cc7ff80af) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5ebfe0778c53..03d631525336 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12028,7 +12028,6 @@ static void intel_mmio_flip_work_func(struct work_struct *w) to_intel_framebuffer(crtc->base.primary->fb); struct drm_i915_gem_object *obj = intel_fb->obj; - i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY); WARN_ON(i915_gem_object_wait(obj, 0, MAX_SCHEDULE_TIMEOUT, NULL) < 0); intel_pipe_update_start(crtc); @@ -12284,6 +12283,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, i915_add_request_no_flush(request); } + i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY); i915_gem_track_fb(intel_fb_obj(old_fb), obj, to_intel_plane(primary)->frontbuffer_bit); mutex_unlock(&dev->struct_mutex); From 9c8f2eed73939aedec3822d0ee776f61211cbb0c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 25 Sep 2016 20:52:54 +0200 Subject: [PATCH 033/104] dt-bindings: mxsfb: Indentation cleanup Clean up the ad-hoc indentation in the documentation, no functional change. Signed-off-by: Marek Vasut Cc: Lucas Stach Cc: Fabio Estevam Cc: Shawn Guo Acked-by: Rob Herring --- .../devicetree/bindings/display/mxsfb.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt b/Documentation/devicetree/bindings/display/mxsfb.txt index 96ec5179c8a0..a4431f2e86ce 100644 --- a/Documentation/devicetree/bindings/display/mxsfb.txt +++ b/Documentation/devicetree/bindings/display/mxsfb.txt @@ -1,20 +1,20 @@ * Freescale MXS LCD Interface (LCDIF) Required properties: -- compatible: Should be "fsl,-lcdif". Supported chips include - imx23 and imx28. -- reg: Address and length of the register set for lcdif -- interrupts: Should contain lcdif interrupts -- display : phandle to display node (see below for details) +- compatible: Should be "fsl,imx23-lcdif" for i.MX23. + Should be "fsl,imx28-lcdif" for i.MX28. +- reg: Address and length of the register set for lcdif +- interrupts: Should contain lcdif interrupts +- display: phandle to display node (see below for details) * display node Required properties: -- bits-per-pixel : <16> for RGB565, <32> for RGB888/666. -- bus-width : number of data lines. Could be <8>, <16>, <18> or <24>. +- bits-per-pixel: <16> for RGB565, <32> for RGB888/666. +- bus-width: number of data lines. Could be <8>, <16>, <18> or <24>. Required sub-node: -- display-timings : Refer to binding doc display-timing.txt for details. +- display-timings: Refer to binding doc display-timing.txt for details. Examples: From 7b920aae917da3486f0084fd1b77b2f59f521309 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 23 Aug 2016 14:56:12 +0200 Subject: [PATCH 034/104] dt-bindings: mxsfb: Add new bindings for the MXSFB driver Add new DT bindings for new MXSFB driver that is using the OF graph to parse the video output structure instead of hard-coding the display properties into the MXSFB node. The old MXSFB fbdev driver bindings are preserved in the same file in the "Old bindings" section. Signed-off-by: Marek Vasut Cc: Rob Herring Cc: Lucas Stach Cc: Fabio Estevam Cc: Shawn Guo Acked-by: Rob Herring --- .../devicetree/bindings/display/mxsfb.txt | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt b/Documentation/devicetree/bindings/display/mxsfb.txt index a4431f2e86ce..472e1ea6c591 100644 --- a/Documentation/devicetree/bindings/display/mxsfb.txt +++ b/Documentation/devicetree/bindings/display/mxsfb.txt @@ -1,10 +1,47 @@ * Freescale MXS LCD Interface (LCDIF) +New bindings: +============= Required properties: - compatible: Should be "fsl,imx23-lcdif" for i.MX23. Should be "fsl,imx28-lcdif" for i.MX28. -- reg: Address and length of the register set for lcdif -- interrupts: Should contain lcdif interrupts + Should be "fsl,imx6sx-lcdif" for i.MX6SX. +- reg: Address and length of the register set for LCDIF +- interrupts: Should contain LCDIF interrupt +- clocks: A list of phandle + clock-specifier pairs, one for each + entry in 'clock-names'. +- clock-names: A list of clock names. For MXSFB it should contain: + - "pix" for the LCDIF block clock + - (MX6SX-only) "axi", "disp_axi" for the bus interface clock + +Required sub-nodes: + - port: The connection to an encoder chip. + +Example: + + lcdif1: display-controller@2220000 { + compatible = "fsl,imx6sx-lcdif", "fsl,imx28-lcdif"; + reg = <0x02220000 0x4000>; + interrupts = ; + clocks = <&clks IMX6SX_CLK_LCDIF1_PIX>, + <&clks IMX6SX_CLK_LCDIF_APB>, + <&clks IMX6SX_CLK_DISPLAY_AXI>; + clock-names = "pix", "axi", "disp_axi"; + + port { + parallel_out: endpoint { + remote-endpoint = <&panel_in_parallel>; + }; + }; + }; + +Deprecated bindings: +==================== +Required properties: +- compatible: Should be "fsl,imx23-lcdif" for i.MX23. + Should be "fsl,imx28-lcdif" for i.MX28. +- reg: Address and length of the register set for LCDIF +- interrupts: Should contain LCDIF interrupts - display: phandle to display node (see below for details) * display node From 45d59d704080cc0c914b7cff24ccf19f12b9ce23 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 18 Aug 2016 20:23:01 +0200 Subject: [PATCH 035/104] drm: Add new driver for MXSFB controller Add new driver for the MXSFB controller found in i.MX23/28/6SX . The MXSFB controller is a simple framebuffer controller with one parallel LCD output. Unlike the MXSFB fbdev driver that is used on these systems now, this driver uses the DRM/KMS framework. Signed-off-by: Marek Vasut Cc: Lucas Stach Cc: Fabio Estevam Cc: Shawn Guo --- MAINTAINERS | 6 + drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/mxsfb/Kconfig | 18 ++ drivers/gpu/drm/mxsfb/Makefile | 2 + drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 241 ++++++++++++++++ drivers/gpu/drm/mxsfb/mxsfb_drv.c | 444 +++++++++++++++++++++++++++++ drivers/gpu/drm/mxsfb/mxsfb_drv.h | 54 ++++ drivers/gpu/drm/mxsfb/mxsfb_out.c | 131 +++++++++ drivers/gpu/drm/mxsfb/mxsfb_regs.h | 114 ++++++++ 10 files changed, 1013 insertions(+) create mode 100644 drivers/gpu/drm/mxsfb/Kconfig create mode 100644 drivers/gpu/drm/mxsfb/Makefile create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_crtc.c create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_drv.c create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_drv.h create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c create mode 100644 drivers/gpu/drm/mxsfb/mxsfb_regs.h diff --git a/MAINTAINERS b/MAINTAINERS index f981ae71a0e9..26fccc165039 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8319,6 +8319,12 @@ T: git git://linuxtv.org/mkrufky/tuners.git S: Maintained F: drivers/media/tuners/mxl5007t.* +MXSFB DRM DRIVER +M: Marek Vasut +S: Supported +F: drivers/gpu/drm/mxsfb/ +F: Documentation/devicetree/bindings/display/mxsfb-drm.txt + MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) M: Hyong-Youb Kim L: netdev@vger.kernel.org diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 95fc0410e129..726d5127f449 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -240,6 +240,8 @@ source "drivers/gpu/drm/mediatek/Kconfig" source "drivers/gpu/drm/zte/Kconfig" +source "drivers/gpu/drm/mxsfb/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACY diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 883f3e75cfbc..b4723e66d1d8 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -89,3 +89,4 @@ obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/ obj-$(CONFIG_DRM_ARCPGU)+= arc/ obj-y += hisilicon/ obj-$(CONFIG_DRM_ZTE) += zte/ +obj-$(CONFIG_DRM_MXSFB) += mxsfb/ diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig new file mode 100644 index 000000000000..0b6cb5958ce7 --- /dev/null +++ b/drivers/gpu/drm/mxsfb/Kconfig @@ -0,0 +1,18 @@ +config DRM_MXS + bool + help + Choose this option to select drivers for MXS FB devices + +config DRM_MXSFB + tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller" + depends on DRM && OF + depends on COMMON_CLK + select DRM_MXS + select DRM_KMS_HELPER + select DRM_KMS_FB_HELPER + select DRM_KMS_CMA_HELPER + help + Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB + LCD controller. + + If M is selected the module will be called mxsfb. diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile new file mode 100644 index 000000000000..857f3a4545ff --- /dev/null +++ b/drivers/gpu/drm/mxsfb/Makefile @@ -0,0 +1,2 @@ +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o +obj-$(CONFIG_DRM_MXSFB) += mxsfb.o diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c new file mode 100644 index 000000000000..081890336ce7 --- /dev/null +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2016 Marek Vasut + * + * This code is based on drivers/video/fbdev/mxsfb.c : + * Copyright (C) 2010 Juergen Beisert, Pengutronix + * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * 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 +#include +#include +#include +#include +#include