mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-03-02 08:44:39 +07:00
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
Summary: - Support for pipeline clock between KMS drivers. . Exynos SoC is required to control clocks across KMS drivers according to Exynos SoC version. So this patch refactos some relevant codes and provides generic solution for it. - Add Exynos5433 SoC support to HDMI parts - HDMI and DECON-TV. - Add HW trigger mode support to CRTC drivers. . In case of using i80 Panel, some Exynos SoC supports HW trigger mode so this patch makes trigger mode - HW or SW trigger - to be set according to SoC version properly. - And some cleanups and regression fixups. * 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (39 commits) drm/exynos: clean up register definions for fimd and decon drm/exynos: decon: clean up interface type drm/exynos: fimd: add HW trigger support drm/exynos: clean up wait_for_vblank drm/exynos: mixer: use generic of_device_get_match_data helper drm/exynos: mixer: remove support for non-dt platforms drm/exynos: hdmi: use generic of_device_get_match_data helper drm/exynos: rotator: use generic of_device_get_match_data helper drm/exynos: fimd: use generic of_device_get_match_data helper drm/exynos: dsi: use generic of_device_get_match_data helper drm/exynos: exynos5433_decon: use generic of_device_get_match_data helper drm/exynos: convert clock_enable crtc callback to pipeline clock drm/exynos/mixer: enable HDMI-PHY before configuring MIXER drm/exynos/decon5433: enable HDMI-PHY before configuring DECON drm/exynos: add support for pipeline clock to the framework drm/exynos: add helper to get crtc from pipe drm/exynos/decon5433: do not protect window in plane disable drm/exynos/decon5433: reset decon on start drm/exynos/decon5433: fix DECON standalone update drm/exynos/hdmi: remove registry dump ...
This commit is contained in:
commit
00c1beab15
@ -5,7 +5,8 @@ Exynos series of SoCs which transfers the image data from a video memory
|
||||
buffer to an external LCD interface.
|
||||
|
||||
Required properties:
|
||||
- compatible: value should be "samsung,exynos5433-decon";
|
||||
- compatible: value should be one of:
|
||||
"samsung,exynos5433-decon", "samsung,exynos5433-decon-tv";
|
||||
- reg: physical base address and length of the DECON registers set.
|
||||
- interrupts: should contain a list of all DECON IP block interrupts in the
|
||||
order: VSYNC, LCD_SYSTEM. The interrupt specifier format
|
||||
@ -16,7 +17,7 @@ Required properties:
|
||||
- clocks: must include clock specifiers corresponding to entries in the
|
||||
clock-names property.
|
||||
- clock-names: list of clock names sorted in the same order as the clocks
|
||||
property. Must contain "aclk_decon", "aclk_smmu_decon0x",
|
||||
property. Must contain "pclk", "aclk_decon", "aclk_smmu_decon0x",
|
||||
"aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk",
|
||||
"sclk_decon_eclk"
|
||||
- ports: contains a port which is connected to mic node. address-cells and
|
||||
|
@ -5,6 +5,7 @@ Required properties:
|
||||
1) "samsung,exynos4210-hdmi"
|
||||
2) "samsung,exynos4212-hdmi"
|
||||
3) "samsung,exynos5420-hdmi"
|
||||
4) "samsung,exynos5433-hdmi"
|
||||
- reg: physical base address of the hdmi and length of memory mapped
|
||||
region.
|
||||
- interrupts: interrupt number to the cpu.
|
||||
@ -12,6 +13,11 @@ Required properties:
|
||||
a) phandle of the gpio controller node.
|
||||
b) pin number within the gpio controller.
|
||||
c) optional flags and pull up/down.
|
||||
- ddc: phandle to the hdmi ddc node
|
||||
- phy: phandle to the hdmi phy node
|
||||
- samsung,syscon-phandle: phandle for system controller node for PMU.
|
||||
|
||||
Required properties for Exynos 4210, 4212, 5420 and 5433:
|
||||
- clocks: list of clock IDs from SoC clock driver.
|
||||
a) hdmi: Gate of HDMI IP bus clock.
|
||||
b) sclk_hdmi: Gate of HDMI special clock.
|
||||
@ -25,9 +31,24 @@ Required properties:
|
||||
sclk_pixel.
|
||||
- clock-names: aliases as per driver requirements for above clock IDs:
|
||||
"hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi".
|
||||
- ddc: phandle to the hdmi ddc node
|
||||
- phy: phandle to the hdmi phy node
|
||||
- samsung,syscon-phandle: phandle for system controller node for PMU.
|
||||
|
||||
Required properties for Exynos 5433:
|
||||
- clocks: list of clock specifiers according to common clock bindings.
|
||||
a) hdmi_pclk: Gate of HDMI IP APB bus.
|
||||
b) hdmi_i_pclk: Gate of HDMI-PHY IP APB bus.
|
||||
d) i_tmds_clk: Gate of HDMI TMDS clock.
|
||||
e) i_pixel_clk: Gate of HDMI pixel clock.
|
||||
f) i_spdif_clk: Gate of HDMI SPDIF clock.
|
||||
g) oscclk: Oscillator clock, used as parent of following *_user clocks
|
||||
in case HDMI-PHY is not operational.
|
||||
h) tmds_clko: TMDS clock generated by HDMI-PHY.
|
||||
i) tmds_clko_user: MUX used to switch between oscclk and tmds_clko,
|
||||
respectively if HDMI-PHY is off and operational.
|
||||
j) pixel_clko: Pixel clock generated by HDMI-PHY.
|
||||
k) pixel_clko_user: MUX used to switch between oscclk and pixel_clko,
|
||||
respectively if HDMI-PHY is off and operational.
|
||||
- clock-names: aliases for above clock specfiers.
|
||||
- samsung,sysreg: handle to syscon used to control the system registers.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -95,7 +95,7 @@ comment "Sub-drivers"
|
||||
|
||||
config DRM_EXYNOS_G2D
|
||||
bool "G2D"
|
||||
depends on !VIDEO_SAMSUNG_S5P_G2D
|
||||
depends on VIDEO_SAMSUNG_S5P_G2D=n
|
||||
select FRAME_VECTOR
|
||||
help
|
||||
Choose this option if you want to use Exynos G2D for DRM.
|
||||
|
@ -2,10 +2,10 @@
|
||||
# Makefile for the drm device driver. This driver provides support for the
|
||||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||
|
||||
exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fbdev.o \
|
||||
exynos_drm_fb.o exynos_drm_gem.o exynos_drm_core.o \
|
||||
exynos_drm_plane.o
|
||||
exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fb.o \
|
||||
exynos_drm_gem.o exynos_drm_core.o exynos_drm_plane.o
|
||||
|
||||
exynosdrm-$(CONFIG_DRM_FBDEV_EMULATION) += exynos_drm_fbdev.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o
|
||||
|
@ -28,6 +28,10 @@
|
||||
#define WINDOWS_NR 3
|
||||
#define MIN_FB_WIDTH_FOR_16WORD_BURST 128
|
||||
|
||||
#define IFTYPE_I80 (1 << 0)
|
||||
#define I80_HW_TRG (1 << 1)
|
||||
#define IFTYPE_HDMI (1 << 2)
|
||||
|
||||
static const char * const decon_clks_name[] = {
|
||||
"pclk",
|
||||
"aclk_decon",
|
||||
@ -38,12 +42,6 @@ static const char * const decon_clks_name[] = {
|
||||
"sclk_decon_eclk",
|
||||
};
|
||||
|
||||
enum decon_iftype {
|
||||
IFTYPE_RGB,
|
||||
IFTYPE_I80,
|
||||
IFTYPE_HDMI
|
||||
};
|
||||
|
||||
enum decon_flag_bits {
|
||||
BIT_CLKS_ENABLED,
|
||||
BIT_IRQS_ENABLED,
|
||||
@ -61,7 +59,7 @@ struct decon_context {
|
||||
struct clk *clks[ARRAY_SIZE(decon_clks_name)];
|
||||
int pipe;
|
||||
unsigned long flags;
|
||||
enum decon_iftype out_type;
|
||||
unsigned long out_type;
|
||||
int first_win;
|
||||
};
|
||||
|
||||
@ -95,7 +93,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
|
||||
|
||||
if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) {
|
||||
val = VIDINTCON0_INTEN;
|
||||
if (ctx->out_type == IFTYPE_I80)
|
||||
if (ctx->out_type & IFTYPE_I80)
|
||||
val |= VIDINTCON0_FRAMEDONE;
|
||||
else
|
||||
val |= VIDINTCON0_INTFRMEN;
|
||||
@ -119,11 +117,11 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
|
||||
|
||||
static void decon_setup_trigger(struct decon_context *ctx)
|
||||
{
|
||||
u32 val = (ctx->out_type != IFTYPE_HDMI)
|
||||
u32 val = !(ctx->out_type & I80_HW_TRG)
|
||||
? TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
|
||||
TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN
|
||||
: TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
|
||||
TRIGCON_HWTRIGMASK_I80_RGB | TRIGCON_HWTRIGEN_I80_RGB;
|
||||
TRIGCON_HWTRIGMASK | TRIGCON_HWTRIGEN;
|
||||
writel(val, ctx->addr + DECON_TRIGCON);
|
||||
}
|
||||
|
||||
@ -136,7 +134,7 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
|
||||
if (test_bit(BIT_SUSPENDED, &ctx->flags))
|
||||
return;
|
||||
|
||||
if (ctx->out_type == IFTYPE_HDMI) {
|
||||
if (ctx->out_type & IFTYPE_HDMI) {
|
||||
m->crtc_hsync_start = m->crtc_hdisplay + 10;
|
||||
m->crtc_hsync_end = m->crtc_htotal - 92;
|
||||
m->crtc_vsync_start = m->crtc_vdisplay + 1;
|
||||
@ -151,17 +149,20 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
|
||||
|
||||
/* lcd on and use command if */
|
||||
val = VIDOUT_LCD_ON;
|
||||
if (ctx->out_type == IFTYPE_I80)
|
||||
if (ctx->out_type & IFTYPE_I80) {
|
||||
val |= VIDOUT_COMMAND_IF;
|
||||
else
|
||||
decon_setup_trigger(ctx);
|
||||
} else {
|
||||
val |= VIDOUT_RGB_IF;
|
||||
}
|
||||
|
||||
writel(val, ctx->addr + DECON_VIDOUTCON0);
|
||||
|
||||
val = VIDTCON2_LINEVAL(m->vdisplay - 1) |
|
||||
VIDTCON2_HOZVAL(m->hdisplay - 1);
|
||||
writel(val, ctx->addr + DECON_VIDTCON2);
|
||||
|
||||
if (ctx->out_type != IFTYPE_I80) {
|
||||
if (!(ctx->out_type & IFTYPE_I80)) {
|
||||
val = VIDTCON00_VBPD_F(
|
||||
m->crtc_vtotal - m->crtc_vsync_end - 1) |
|
||||
VIDTCON00_VFPD_F(
|
||||
@ -183,10 +184,10 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
|
||||
writel(val, ctx->addr + DECON_VIDTCON11);
|
||||
}
|
||||
|
||||
decon_setup_trigger(ctx);
|
||||
|
||||
/* enable output and display signal */
|
||||
decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID | VIDCON0_ENVID_F, ~0);
|
||||
|
||||
decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
|
||||
}
|
||||
|
||||
static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
|
||||
@ -300,7 +301,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
|
||||
val = dma_addr + pitch * state->src.h;
|
||||
writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
|
||||
|
||||
if (ctx->out_type != IFTYPE_HDMI)
|
||||
if (!(ctx->out_type & IFTYPE_HDMI))
|
||||
val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14)
|
||||
| BIT_VAL(state->crtc.w * bpp, 13, 0);
|
||||
else
|
||||
@ -312,9 +313,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
|
||||
|
||||
/* window enable */
|
||||
decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0);
|
||||
|
||||
/* standalone update */
|
||||
decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
|
||||
}
|
||||
|
||||
static void decon_disable_plane(struct exynos_drm_crtc *crtc,
|
||||
@ -326,15 +324,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
|
||||
if (test_bit(BIT_SUSPENDED, &ctx->flags))
|
||||
return;
|
||||
|
||||
decon_shadow_protect_win(ctx, win, true);
|
||||
|
||||
/* window disable */
|
||||
decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0);
|
||||
|
||||
decon_shadow_protect_win(ctx, win, false);
|
||||
|
||||
/* standalone update */
|
||||
decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
|
||||
}
|
||||
|
||||
static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
|
||||
@ -348,7 +338,10 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
|
||||
for (i = ctx->first_win; i < WINDOWS_NR; i++)
|
||||
decon_shadow_protect_win(ctx, i, false);
|
||||
|
||||
if (ctx->out_type == IFTYPE_I80)
|
||||
/* standalone update */
|
||||
decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
|
||||
|
||||
if (ctx->out_type & IFTYPE_I80)
|
||||
set_bit(BIT_WIN_UPDATED, &ctx->flags);
|
||||
}
|
||||
|
||||
@ -374,7 +367,7 @@ static void decon_swreset(struct decon_context *ctx)
|
||||
|
||||
WARN(tries == 0, "failed to software reset DECON\n");
|
||||
|
||||
if (ctx->out_type != IFTYPE_HDMI)
|
||||
if (!(ctx->out_type & IFTYPE_HDMI))
|
||||
return;
|
||||
|
||||
writel(VIDCON0_CLKVALUP | VIDCON0_VLCKFREE, ctx->addr + DECON_VIDCON0);
|
||||
@ -383,7 +376,9 @@ static void decon_swreset(struct decon_context *ctx)
|
||||
writel(VIDCON1_VCLK_RUN_VDEN_DISABLE, ctx->addr + DECON_VIDCON1);
|
||||
writel(CRCCTRL_CRCEN | CRCCTRL_CRCSTART_F | CRCCTRL_CRCCLKEN,
|
||||
ctx->addr + DECON_CRCCTRL);
|
||||
decon_setup_trigger(ctx);
|
||||
|
||||
if (ctx->out_type & IFTYPE_I80)
|
||||
decon_setup_trigger(ctx);
|
||||
}
|
||||
|
||||
static void decon_enable(struct exynos_drm_crtc *crtc)
|
||||
@ -395,8 +390,12 @@ static void decon_enable(struct exynos_drm_crtc *crtc)
|
||||
|
||||
pm_runtime_get_sync(ctx->dev);
|
||||
|
||||
exynos_drm_pipe_clk_enable(crtc, true);
|
||||
|
||||
set_bit(BIT_CLKS_ENABLED, &ctx->flags);
|
||||
|
||||
decon_swreset(ctx);
|
||||
|
||||
/* if vblank was enabled status, enable it again. */
|
||||
if (test_and_clear_bit(BIT_IRQS_ENABLED, &ctx->flags))
|
||||
decon_enable_vblank(ctx->crtc);
|
||||
@ -424,6 +423,8 @@ static void decon_disable(struct exynos_drm_crtc *crtc)
|
||||
|
||||
clear_bit(BIT_CLKS_ENABLED, &ctx->flags);
|
||||
|
||||
exynos_drm_pipe_clk_enable(crtc, false);
|
||||
|
||||
pm_runtime_put_sync(ctx->dev);
|
||||
|
||||
set_bit(BIT_SUSPENDED, &ctx->flags);
|
||||
@ -459,8 +460,10 @@ static void decon_clear_channels(struct exynos_drm_crtc *crtc)
|
||||
decon_shadow_protect_win(ctx, win, true);
|
||||
decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0);
|
||||
decon_shadow_protect_win(ctx, win, false);
|
||||
decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
|
||||
}
|
||||
|
||||
decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
|
||||
|
||||
/* TODO: wait for possible vsync */
|
||||
msleep(50);
|
||||
|
||||
@ -509,7 +512,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
|
||||
}
|
||||
|
||||
exynos_plane = &ctx->planes[ctx->first_win];
|
||||
out_type = (ctx->out_type == IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI
|
||||
out_type = (ctx->out_type & IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI
|
||||
: EXYNOS_DISPLAY_TYPE_LCD;
|
||||
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
|
||||
ctx->pipe, out_type,
|
||||
@ -617,11 +620,11 @@ static const struct dev_pm_ops exynos5433_decon_pm_ops = {
|
||||
static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos5433-decon",
|
||||
.data = (void *)IFTYPE_RGB
|
||||
.data = (void *)I80_HW_TRG
|
||||
},
|
||||
{
|
||||
.compatible = "samsung,exynos5433-decon-tv",
|
||||
.data = (void *)IFTYPE_HDMI
|
||||
.data = (void *)(I80_HW_TRG | IFTYPE_HDMI)
|
||||
},
|
||||
{},
|
||||
};
|
||||
@ -629,7 +632,6 @@ MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match);
|
||||
|
||||
static int exynos5433_decon_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct decon_context *ctx;
|
||||
struct resource *res;
|
||||
@ -642,14 +644,14 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
|
||||
|
||||
__set_bit(BIT_SUSPENDED, &ctx->flags);
|
||||
ctx->dev = dev;
|
||||
ctx->out_type = (unsigned long)of_device_get_match_data(dev);
|
||||
|
||||
of_id = of_match_device(exynos5433_decon_driver_dt_match, &pdev->dev);
|
||||
ctx->out_type = (enum decon_iftype)of_id->data;
|
||||
|
||||
if (ctx->out_type == IFTYPE_HDMI)
|
||||
if (ctx->out_type & IFTYPE_HDMI) {
|
||||
ctx->first_win = 1;
|
||||
else if (of_get_child_by_name(dev->of_node, "i80-if-timings"))
|
||||
ctx->out_type = IFTYPE_I80;
|
||||
} else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) {
|
||||
ctx->out_type = IFTYPE_I80;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
|
||||
struct clk *clk;
|
||||
@ -674,7 +676,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
|
||||
(ctx->out_type == IFTYPE_I80) ? "lcd_sys" : "vsync");
|
||||
(ctx->out_type & IFTYPE_I80) ? "lcd_sys" : "vsync");
|
||||
if (!res) {
|
||||
dev_err(dev, "cannot find IRQ resource\n");
|
||||
return -ENXIO;
|
||||
|
@ -593,7 +593,6 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = {
|
||||
.commit = decon_commit,
|
||||
.enable_vblank = decon_enable_vblank,
|
||||
.disable_vblank = decon_disable_vblank,
|
||||
.wait_for_vblank = decon_wait_for_vblank,
|
||||
.atomic_begin = decon_atomic_begin,
|
||||
.update_plane = decon_update_plane,
|
||||
.disable_plane = decon_disable_plane,
|
||||
|
@ -48,14 +48,11 @@ int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data,
|
||||
{
|
||||
struct exynos_dp_device *dp = to_dp(plat_data);
|
||||
struct drm_encoder *encoder = &dp->encoder;
|
||||
struct exynos_drm_crtc *crtc;
|
||||
|
||||
if (!encoder)
|
||||
return -1;
|
||||
if (!encoder->crtc)
|
||||
return -EPERM;
|
||||
|
||||
crtc = to_exynos_crtc(encoder->crtc);
|
||||
if (crtc && crtc->ops && crtc->ops->clock_enable)
|
||||
crtc->ops->clock_enable(crtc, enable);
|
||||
exynos_drm_pipe_clk_enable(to_exynos_crtc(encoder->crtc), enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
|
||||
list_for_each_entry_continue_reverse(subdrv, &exynos_drm_subdrv_list, list) {
|
||||
if (subdrv->close)
|
||||
subdrv->close(dev, subdrv->dev, file);
|
||||
}
|
||||
|
@ -157,9 +157,8 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
|
||||
|
||||
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct exynos_drm_private *private = dev->dev_private;
|
||||
struct exynos_drm_crtc *exynos_crtc =
|
||||
to_exynos_crtc(private->crtc[pipe]);
|
||||
struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev,
|
||||
pipe);
|
||||
|
||||
if (exynos_crtc->ops->enable_vblank)
|
||||
return exynos_crtc->ops->enable_vblank(exynos_crtc);
|
||||
@ -169,9 +168,8 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
|
||||
|
||||
void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct exynos_drm_private *private = dev->dev_private;
|
||||
struct exynos_drm_crtc *exynos_crtc =
|
||||
to_exynos_crtc(private->crtc[pipe]);
|
||||
struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev,
|
||||
pipe);
|
||||
|
||||
if (exynos_crtc->ops->disable_vblank)
|
||||
exynos_crtc->ops->disable_vblank(exynos_crtc);
|
||||
|
@ -120,8 +120,6 @@ struct exynos_drm_plane_config {
|
||||
* @commit: set current hw specific display mode to hw.
|
||||
* @enable_vblank: specific driver callback for enabling vblank interrupt.
|
||||
* @disable_vblank: specific driver callback for disabling vblank interrupt.
|
||||
* @wait_for_vblank: wait for vblank interrupt to make sure that
|
||||
* hardware overlay is updated.
|
||||
* @atomic_check: validate state
|
||||
* @atomic_begin: prepare device to receive an update
|
||||
* @atomic_flush: mark the end of device update
|
||||
@ -129,10 +127,6 @@ struct exynos_drm_plane_config {
|
||||
* @disable_plane: disable hardware specific overlay.
|
||||
* @te_handler: trigger to transfer video image at the tearing effect
|
||||
* synchronization signal if there is a page flip request.
|
||||
* @clock_enable: optional function enabling/disabling display domain clock,
|
||||
* called from exynos-dp driver before powering up (with
|
||||
* 'enable' argument as true) and after powering down (with
|
||||
* 'enable' as false).
|
||||
*/
|
||||
struct exynos_drm_crtc;
|
||||
struct exynos_drm_crtc_ops {
|
||||
@ -141,7 +135,6 @@ struct exynos_drm_crtc_ops {
|
||||
void (*commit)(struct exynos_drm_crtc *crtc);
|
||||
int (*enable_vblank)(struct exynos_drm_crtc *crtc);
|
||||
void (*disable_vblank)(struct exynos_drm_crtc *crtc);
|
||||
void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
|
||||
int (*atomic_check)(struct exynos_drm_crtc *crtc,
|
||||
struct drm_crtc_state *state);
|
||||
void (*atomic_begin)(struct exynos_drm_crtc *crtc);
|
||||
@ -151,7 +144,10 @@ struct exynos_drm_crtc_ops {
|
||||
struct exynos_drm_plane *plane);
|
||||
void (*atomic_flush)(struct exynos_drm_crtc *crtc);
|
||||
void (*te_handler)(struct exynos_drm_crtc *crtc);
|
||||
void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable);
|
||||
};
|
||||
|
||||
struct exynos_drm_clk {
|
||||
void (*enable)(struct exynos_drm_clk *clk, bool enable);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -182,8 +178,16 @@ struct exynos_drm_crtc {
|
||||
atomic_t pending_update;
|
||||
const struct exynos_drm_crtc_ops *ops;
|
||||
void *ctx;
|
||||
struct exynos_drm_clk *pipe_clk;
|
||||
};
|
||||
|
||||
static inline void exynos_drm_pipe_clk_enable(struct exynos_drm_crtc *crtc,
|
||||
bool enable)
|
||||
{
|
||||
if (crtc->pipe_clk)
|
||||
crtc->pipe_clk->enable(crtc->pipe_clk, enable);
|
||||
}
|
||||
|
||||
struct exynos_drm_g2d_private {
|
||||
struct device *dev;
|
||||
struct list_head inuse_cmdlist;
|
||||
@ -232,6 +236,14 @@ struct exynos_drm_private {
|
||||
wait_queue_head_t wait;
|
||||
};
|
||||
|
||||
static inline struct exynos_drm_crtc *
|
||||
exynos_drm_crtc_from_pipe(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct exynos_drm_private *private = dev->dev_private;
|
||||
|
||||
return to_exynos_crtc(private->crtc[pipe]);
|
||||
}
|
||||
|
||||
static inline struct device *to_dma_dev(struct drm_device *dev)
|
||||
{
|
||||
struct exynos_drm_private *priv = dev->dev_private;
|
||||
|
@ -280,7 +280,7 @@ struct exynos_dsi {
|
||||
spinlock_t transfer_lock; /* protects transfer_list */
|
||||
struct list_head transfer_list;
|
||||
|
||||
struct exynos_dsi_driver_data *driver_data;
|
||||
const struct exynos_dsi_driver_data *driver_data;
|
||||
struct device_node *bridge_node;
|
||||
};
|
||||
|
||||
@ -532,15 +532,6 @@ static const struct of_device_id exynos_dsi_of_match[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data(
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(exynos_dsi_of_match, &pdev->dev);
|
||||
|
||||
return (struct exynos_dsi_driver_data *)of_id->data;
|
||||
}
|
||||
|
||||
static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
|
||||
{
|
||||
if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
|
||||
@ -564,7 +555,7 @@ static void exynos_dsi_reset(struct exynos_dsi *dsi)
|
||||
static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
|
||||
unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s)
|
||||
{
|
||||
struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
unsigned long best_freq = 0;
|
||||
u32 min_delta = 0xffffffff;
|
||||
u8 p_min, p_max;
|
||||
@ -618,7 +609,7 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
|
||||
static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
|
||||
unsigned long freq)
|
||||
{
|
||||
struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
unsigned long fin, fout;
|
||||
int timeout;
|
||||
u8 p, s;
|
||||
@ -712,7 +703,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
|
||||
|
||||
static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
|
||||
{
|
||||
struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
const unsigned int *reg_values = driver_data->reg_values;
|
||||
u32 reg;
|
||||
|
||||
@ -790,7 +781,7 @@ static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane)
|
||||
|
||||
static int exynos_dsi_init_link(struct exynos_dsi *dsi)
|
||||
{
|
||||
struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
int timeout;
|
||||
u32 reg;
|
||||
u32 lanes_mask;
|
||||
@ -1334,7 +1325,7 @@ static void exynos_dsi_disable_irq(struct exynos_dsi *dsi)
|
||||
|
||||
static int exynos_dsi_init(struct exynos_dsi *dsi)
|
||||
{
|
||||
struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
|
||||
exynos_dsi_reset(dsi);
|
||||
exynos_dsi_enable_irq(dsi);
|
||||
@ -1833,7 +1824,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
|
||||
dsi->dsi_host.dev = dev;
|
||||
|
||||
dsi->dev = dev;
|
||||
dsi->driver_data = exynos_dsi_get_driver_data(pdev);
|
||||
dsi->driver_data = of_device_get_match_data(dev);
|
||||
|
||||
ret = exynos_dsi_parse_dt(dsi);
|
||||
if (ret)
|
||||
@ -1917,7 +1908,7 @@ static int __maybe_unused exynos_dsi_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_encoder *encoder = dev_get_drvdata(dev);
|
||||
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
|
||||
struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
int ret, i;
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
@ -1948,7 +1939,7 @@ static int __maybe_unused exynos_dsi_resume(struct device *dev)
|
||||
{
|
||||
struct drm_encoder *encoder = dev_get_drvdata(dev);
|
||||
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
|
||||
struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
||||
int ret, i;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
||||
|
@ -199,17 +199,6 @@ dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index)
|
||||
return exynos_fb->dma_addr[index];
|
||||
}
|
||||
|
||||
static void exynos_drm_output_poll_changed(struct drm_device *dev)
|
||||
{
|
||||
struct exynos_drm_private *private = dev->dev_private;
|
||||
struct drm_fb_helper *fb_helper = private->fb_helper;
|
||||
|
||||
if (fb_helper)
|
||||
drm_fb_helper_hotplug_event(fb_helper);
|
||||
else
|
||||
exynos_drm_fbdev_init(dev);
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
|
||||
.fb_create = exynos_user_fb_create,
|
||||
.output_poll_changed = exynos_drm_output_poll_changed,
|
||||
|
@ -311,3 +311,14 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
|
||||
|
||||
drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper);
|
||||
}
|
||||
|
||||
void exynos_drm_output_poll_changed(struct drm_device *dev)
|
||||
{
|
||||
struct exynos_drm_private *private = dev->dev_private;
|
||||
struct drm_fb_helper *fb_helper = private->fb_helper;
|
||||
|
||||
if (fb_helper)
|
||||
drm_fb_helper_hotplug_event(fb_helper);
|
||||
else
|
||||
exynos_drm_fbdev_init(dev);
|
||||
}
|
||||
|
@ -15,9 +15,30 @@
|
||||
#ifndef _EXYNOS_DRM_FBDEV_H_
|
||||
#define _EXYNOS_DRM_FBDEV_H_
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
|
||||
int exynos_drm_fbdev_init(struct drm_device *dev);
|
||||
int exynos_drm_fbdev_reinit(struct drm_device *dev);
|
||||
void exynos_drm_fbdev_fini(struct drm_device *dev);
|
||||
void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
|
||||
void exynos_drm_output_poll_changed(struct drm_device *dev);
|
||||
|
||||
#else
|
||||
|
||||
static inline int exynos_drm_fbdev_init(struct drm_device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void exynos_drm_fbdev_fini(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
#define exynos_drm_output_poll_changed (NULL)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -68,10 +68,15 @@
|
||||
/* color key value register for hardware window 1 ~ 4. */
|
||||
#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8))
|
||||
|
||||
/* I80 / RGB trigger control register */
|
||||
/* I80 trigger control register */
|
||||
#define TRIGCON 0x1A4
|
||||
#define TRGMODE_I80_RGB_ENABLE_I80 (1 << 0)
|
||||
#define SWTRGCMD_I80_RGB_ENABLE (1 << 1)
|
||||
#define TRGMODE_ENABLE (1 << 0)
|
||||
#define SWTRGCMD_ENABLE (1 << 1)
|
||||
/* Exynos3250, 3472, 4415, 5260 5410, 5420 and 5422 only supported. */
|
||||
#define HWTRGEN_ENABLE (1 << 3)
|
||||
#define HWTRGMASK_ENABLE (1 << 4)
|
||||
/* Exynos3250, 3472, 4415, 5260, 5420 and 5422 only supported. */
|
||||
#define HWTRIGEN_PER_ENABLE (1 << 31)
|
||||
|
||||
/* display mode change control register except exynos4 */
|
||||
#define VIDOUT_CON 0x000
|
||||
@ -89,12 +94,16 @@
|
||||
/* FIMD has totally five hardware windows. */
|
||||
#define WINDOWS_NR 5
|
||||
|
||||
/* HW trigger flag on i80 panel. */
|
||||
#define I80_HW_TRG (1 << 1)
|
||||
|
||||
struct fimd_driver_data {
|
||||
unsigned int timing_base;
|
||||
unsigned int lcdblk_offset;
|
||||
unsigned int lcdblk_vt_shift;
|
||||
unsigned int lcdblk_bypass_shift;
|
||||
unsigned int lcdblk_mic_bypass_shift;
|
||||
unsigned int trg_type;
|
||||
|
||||
unsigned int has_shadowcon:1;
|
||||
unsigned int has_clksel:1;
|
||||
@ -102,20 +111,26 @@ struct fimd_driver_data {
|
||||
unsigned int has_vidoutcon:1;
|
||||
unsigned int has_vtsel:1;
|
||||
unsigned int has_mic_bypass:1;
|
||||
unsigned int has_dp_clk:1;
|
||||
unsigned int has_hw_trigger:1;
|
||||
unsigned int has_trigger_per_te:1;
|
||||
};
|
||||
|
||||
static struct fimd_driver_data s3c64xx_fimd_driver_data = {
|
||||
.timing_base = 0x0,
|
||||
.has_clksel = 1,
|
||||
.has_limited_fmt = 1,
|
||||
.has_hw_trigger = 1,
|
||||
};
|
||||
|
||||
static struct fimd_driver_data exynos3_fimd_driver_data = {
|
||||
.timing_base = 0x20000,
|
||||
.lcdblk_offset = 0x210,
|
||||
.lcdblk_bypass_shift = 1,
|
||||
.trg_type = I80_HW_TRG,
|
||||
.has_shadowcon = 1,
|
||||
.has_vidoutcon = 1,
|
||||
.has_trigger_per_te = 1,
|
||||
};
|
||||
|
||||
static struct fimd_driver_data exynos4_fimd_driver_data = {
|
||||
@ -132,9 +147,11 @@ static struct fimd_driver_data exynos4415_fimd_driver_data = {
|
||||
.lcdblk_offset = 0x210,
|
||||
.lcdblk_vt_shift = 10,
|
||||
.lcdblk_bypass_shift = 1,
|
||||
.trg_type = I80_HW_TRG,
|
||||
.has_shadowcon = 1,
|
||||
.has_vidoutcon = 1,
|
||||
.has_vtsel = 1,
|
||||
.has_trigger_per_te = 1,
|
||||
};
|
||||
|
||||
static struct fimd_driver_data exynos5_fimd_driver_data = {
|
||||
@ -145,6 +162,7 @@ static struct fimd_driver_data exynos5_fimd_driver_data = {
|
||||
.has_shadowcon = 1,
|
||||
.has_vidoutcon = 1,
|
||||
.has_vtsel = 1,
|
||||
.has_dp_clk = 1,
|
||||
};
|
||||
|
||||
static struct fimd_driver_data exynos5420_fimd_driver_data = {
|
||||
@ -153,10 +171,14 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = {
|
||||
.lcdblk_vt_shift = 24,
|
||||
.lcdblk_bypass_shift = 15,
|
||||
.lcdblk_mic_bypass_shift = 11,
|
||||
.trg_type = I80_HW_TRG,
|
||||
.has_shadowcon = 1,
|
||||
.has_vidoutcon = 1,
|
||||
.has_vtsel = 1,
|
||||
.has_mic_bypass = 1,
|
||||
.has_dp_clk = 1,
|
||||
.has_hw_trigger = 1,
|
||||
.has_trigger_per_te = 1,
|
||||
};
|
||||
|
||||
struct fimd_context {
|
||||
@ -182,8 +204,9 @@ struct fimd_context {
|
||||
atomic_t win_updated;
|
||||
atomic_t triggering;
|
||||
|
||||
struct fimd_driver_data *driver_data;
|
||||
const struct fimd_driver_data *driver_data;
|
||||
struct drm_encoder *encoder;
|
||||
struct exynos_drm_clk dp_clk;
|
||||
};
|
||||
|
||||
static const struct of_device_id fimd_driver_dt_match[] = {
|
||||
@ -219,15 +242,6 @@ static const uint32_t fimd_formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
static inline struct fimd_driver_data *drm_fimd_get_driver_data(
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(fimd_driver_dt_match, &pdev->dev);
|
||||
|
||||
return (struct fimd_driver_data *)of_id->data;
|
||||
}
|
||||
|
||||
static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
|
||||
{
|
||||
struct fimd_context *ctx = crtc->ctx;
|
||||
@ -400,11 +414,31 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
|
||||
return (clkdiv < 0x100) ? clkdiv : 0xff;
|
||||
}
|
||||
|
||||
static void fimd_setup_trigger(struct fimd_context *ctx)
|
||||
{
|
||||
void __iomem *timing_base = ctx->regs + ctx->driver_data->timing_base;
|
||||
u32 trg_type = ctx->driver_data->trg_type;
|
||||
u32 val = readl(timing_base + TRIGCON);
|
||||
|
||||
val &= ~(TRGMODE_ENABLE);
|
||||
|
||||
if (trg_type == I80_HW_TRG) {
|
||||
if (ctx->driver_data->has_hw_trigger)
|
||||
val |= HWTRGEN_ENABLE | HWTRGMASK_ENABLE;
|
||||
if (ctx->driver_data->has_trigger_per_te)
|
||||
val |= HWTRIGEN_PER_ENABLE;
|
||||
} else {
|
||||
val |= TRGMODE_ENABLE;
|
||||
}
|
||||
|
||||
writel(val, timing_base + TRIGCON);
|
||||
}
|
||||
|
||||
static void fimd_commit(struct exynos_drm_crtc *crtc)
|
||||
{
|
||||
struct fimd_context *ctx = crtc->ctx;
|
||||
struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
|
||||
struct fimd_driver_data *driver_data = ctx->driver_data;
|
||||
const struct fimd_driver_data *driver_data = ctx->driver_data;
|
||||
void *timing_base = ctx->regs + driver_data->timing_base;
|
||||
u32 val, clkdiv;
|
||||
|
||||
@ -495,6 +529,8 @@ static void fimd_commit(struct exynos_drm_crtc *crtc)
|
||||
VIDTCON2_HOZVAL_E(mode->hdisplay - 1);
|
||||
writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
|
||||
|
||||
fimd_setup_trigger(ctx);
|
||||
|
||||
/*
|
||||
* fields of register with prefix '_F' would be updated
|
||||
* at vsync(same as dma start)
|
||||
@ -827,7 +863,7 @@ static void fimd_disable(struct exynos_drm_crtc *crtc)
|
||||
static void fimd_trigger(struct device *dev)
|
||||
{
|
||||
struct fimd_context *ctx = dev_get_drvdata(dev);
|
||||
struct fimd_driver_data *driver_data = ctx->driver_data;
|
||||
const struct fimd_driver_data *driver_data = ctx->driver_data;
|
||||
void *timing_base = ctx->regs + driver_data->timing_base;
|
||||
u32 reg;
|
||||
|
||||
@ -842,7 +878,7 @@ static void fimd_trigger(struct device *dev)
|
||||
atomic_set(&ctx->triggering, 1);
|
||||
|
||||
reg = readl(timing_base + TRIGCON);
|
||||
reg |= (TRGMODE_I80_RGB_ENABLE_I80 | SWTRGCMD_I80_RGB_ENABLE);
|
||||
reg |= (TRGMODE_ENABLE | SWTRGCMD_ENABLE);
|
||||
writel(reg, timing_base + TRIGCON);
|
||||
|
||||
/*
|
||||
@ -856,11 +892,15 @@ static void fimd_trigger(struct device *dev)
|
||||
static void fimd_te_handler(struct exynos_drm_crtc *crtc)
|
||||
{
|
||||
struct fimd_context *ctx = crtc->ctx;
|
||||
u32 trg_type = ctx->driver_data->trg_type;
|
||||
|
||||
/* Checks the crtc is detached already from encoder */
|
||||
if (ctx->pipe < 0 || !ctx->drm_dev)
|
||||
return;
|
||||
|
||||
if (trg_type == I80_HW_TRG)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If there is a page flip request, triggers and handles the page flip
|
||||
* event so that current fb can be updated into panel GRAM.
|
||||
@ -868,6 +908,7 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc)
|
||||
if (atomic_add_unless(&ctx->win_updated, -1, 0))
|
||||
fimd_trigger(ctx->dev);
|
||||
|
||||
out:
|
||||
/* Wakes up vsync event queue */
|
||||
if (atomic_read(&ctx->wait_vsync_event)) {
|
||||
atomic_set(&ctx->wait_vsync_event, 0);
|
||||
@ -878,21 +919,12 @@ static void fimd_te_handler(struct exynos_drm_crtc *crtc)
|
||||
drm_crtc_handle_vblank(&ctx->crtc->base);
|
||||
}
|
||||
|
||||
static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable)
|
||||
static void fimd_dp_clock_enable(struct exynos_drm_clk *clk, bool enable)
|
||||
{
|
||||
struct fimd_context *ctx = crtc->ctx;
|
||||
u32 val;
|
||||
struct fimd_context *ctx = container_of(clk, struct fimd_context,
|
||||
dp_clk);
|
||||
u32 val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
|
||||
|
||||
/*
|
||||
* Only Exynos 5250, 5260, 5410 and 542x requires enabling DP/MIE
|
||||
* clock. On these SoCs the bootloader may enable it but any
|
||||
* power domain off/on will reset it to disable state.
|
||||
*/
|
||||
if (ctx->driver_data != &exynos5_fimd_driver_data ||
|
||||
ctx->driver_data != &exynos5420_fimd_driver_data)
|
||||
return;
|
||||
|
||||
val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
|
||||
writel(val, ctx->regs + DP_MIE_CLKCON);
|
||||
}
|
||||
|
||||
@ -902,13 +934,11 @@ static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
|
||||
.commit = fimd_commit,
|
||||
.enable_vblank = fimd_enable_vblank,
|
||||
.disable_vblank = fimd_disable_vblank,
|
||||
.wait_for_vblank = fimd_wait_for_vblank,
|
||||
.atomic_begin = fimd_atomic_begin,
|
||||
.update_plane = fimd_update_plane,
|
||||
.disable_plane = fimd_disable_plane,
|
||||
.atomic_flush = fimd_atomic_flush,
|
||||
.te_handler = fimd_te_handler,
|
||||
.clock_enable = fimd_dp_clock_enable,
|
||||
};
|
||||
|
||||
static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
|
||||
@ -987,6 +1017,11 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
|
||||
if (IS_ERR(ctx->crtc))
|
||||
return PTR_ERR(ctx->crtc);
|
||||
|
||||
if (ctx->driver_data->has_dp_clk) {
|
||||
ctx->dp_clk.enable = fimd_dp_clock_enable;
|
||||
ctx->crtc->pipe_clk = &ctx->dp_clk;
|
||||
}
|
||||
|
||||
if (ctx->encoder)
|
||||
exynos_dpi_bind(drm_dev, ctx->encoder);
|
||||
|
||||
@ -1035,7 +1070,7 @@ static int fimd_probe(struct platform_device *pdev)
|
||||
|
||||
ctx->dev = dev;
|
||||
ctx->suspended = true;
|
||||
ctx->driver_data = drm_fimd_get_driver_data(pdev);
|
||||
ctx->driver_data = of_device_get_match_data(dev);
|
||||
|
||||
if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
|
||||
ctx->vidcon1 |= VIDCON1_INV_VDEN;
|
||||
|
@ -129,7 +129,7 @@ static void mic_set_path(struct exynos_mic *mic, bool enable)
|
||||
} else
|
||||
val &= ~(MIC0_RGB_MUX | MIC0_I80_MUX | MIC0_ON_MUX);
|
||||
|
||||
regmap_write(mic->sysreg, DSD_CFG_MUX, val);
|
||||
ret = regmap_write(mic->sysreg, DSD_CFG_MUX, val);
|
||||
if (ret)
|
||||
DRM_ERROR("mic: Failed to read system register\n");
|
||||
}
|
||||
@ -457,6 +457,7 @@ static int exynos_mic_probe(struct platform_device *pdev)
|
||||
"samsung,disp-syscon");
|
||||
if (IS_ERR(mic->sysreg)) {
|
||||
DRM_ERROR("mic: Failed to get system register.\n");
|
||||
ret = PTR_ERR(mic->sysreg);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,10 @@
|
||||
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/exynos_drm.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/exynos_drm.h>
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_drm_crtc.h"
|
||||
#include "exynos_drm_fb.h"
|
||||
@ -57,11 +58,12 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
|
||||
}
|
||||
|
||||
static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
|
||||
|
||||
{
|
||||
struct drm_plane_state *state = &exynos_state->base;
|
||||
struct drm_crtc *crtc = exynos_state->base.crtc;
|
||||
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct drm_crtc_state *crtc_state =
|
||||
drm_atomic_get_existing_crtc_state(state->state, crtc);
|
||||
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
|
||||
int crtc_x, crtc_y;
|
||||
unsigned int crtc_w, crtc_h;
|
||||
unsigned int src_x, src_y;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
@ -696,7 +697,6 @@ static int rotator_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rot_context *rot;
|
||||
struct exynos_drm_ippdrv *ippdrv;
|
||||
const struct of_device_id *match;
|
||||
int ret;
|
||||
|
||||
if (!dev->of_node) {
|
||||
@ -708,13 +708,8 @@ static int rotator_probe(struct platform_device *pdev)
|
||||
if (!rot)
|
||||
return -ENOMEM;
|
||||
|
||||
match = of_match_node(exynos_rotator_match, dev->of_node);
|
||||
if (!match) {
|
||||
dev_err(dev, "failed to match node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
rot->limit_tbl = (struct rot_limit_table *)match->data;
|
||||
|
||||
rot->limit_tbl = (struct rot_limit_table *)
|
||||
of_device_get_match_data(dev);
|
||||
rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
rot->regs = devm_ioremap_resource(dev, rot->regs_res);
|
||||
if (IS_ERR(rot->regs))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/component.h>
|
||||
|
||||
#include <drm/exynos_drm.h>
|
||||
@ -103,8 +104,6 @@ struct mixer_context {
|
||||
|
||||
struct mixer_resources mixer_res;
|
||||
enum mixer_version_id mxr_ver;
|
||||
wait_queue_head_t wait_vsync_queue;
|
||||
atomic_t wait_vsync_event;
|
||||
};
|
||||
|
||||
struct mixer_drv_data {
|
||||
@ -787,12 +786,6 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
|
||||
|
||||
exynos_drm_crtc_finish_update(ctx->crtc, plane);
|
||||
}
|
||||
|
||||
/* set wait vsync event to zero and wake up queue. */
|
||||
if (atomic_read(&ctx->wait_vsync_event)) {
|
||||
atomic_set(&ctx->wait_vsync_event, 0);
|
||||
wake_up(&ctx->wait_vsync_queue);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@ -1027,34 +1020,6 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
|
||||
mixer_vsync_set_update(mixer_ctx, true);
|
||||
}
|
||||
|
||||
static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
|
||||
{
|
||||
struct mixer_context *mixer_ctx = crtc->ctx;
|
||||
int err;
|
||||
|
||||
if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
|
||||
return;
|
||||
|
||||
err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
|
||||
if (err < 0) {
|
||||
DRM_DEBUG_KMS("failed to acquire vblank counter\n");
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_set(&mixer_ctx->wait_vsync_event, 1);
|
||||
|
||||
/*
|
||||
* wait for MIXER to signal VSYNC interrupt or return after
|
||||
* timeout which is set to 50ms (refresh rate of 20).
|
||||
*/
|
||||
if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
|
||||
!atomic_read(&mixer_ctx->wait_vsync_event),
|
||||
HZ/20))
|
||||
DRM_DEBUG_KMS("vblank wait timed out.\n");
|
||||
|
||||
drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
|
||||
}
|
||||
|
||||
static void mixer_enable(struct exynos_drm_crtc *crtc)
|
||||
{
|
||||
struct mixer_context *ctx = crtc->ctx;
|
||||
@ -1065,6 +1030,8 @@ static void mixer_enable(struct exynos_drm_crtc *crtc)
|
||||
|
||||
pm_runtime_get_sync(ctx->dev);
|
||||
|
||||
exynos_drm_pipe_clk_enable(crtc, true);
|
||||
|
||||
mixer_vsync_set_update(ctx, false);
|
||||
|
||||
mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
|
||||
@ -1094,6 +1061,8 @@ static void mixer_disable(struct exynos_drm_crtc *crtc)
|
||||
for (i = 0; i < MIXER_WIN_NR; i++)
|
||||
mixer_disable_plane(crtc, &ctx->planes[i]);
|
||||
|
||||
exynos_drm_pipe_clk_enable(crtc, false);
|
||||
|
||||
pm_runtime_put(ctx->dev);
|
||||
|
||||
clear_bit(MXR_BIT_POWERED, &ctx->flags);
|
||||
@ -1126,7 +1095,6 @@ static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
|
||||
.disable = mixer_disable,
|
||||
.enable_vblank = mixer_enable_vblank,
|
||||
.disable_vblank = mixer_disable_vblank,
|
||||
.wait_for_vblank = mixer_wait_for_vblank,
|
||||
.atomic_begin = mixer_atomic_begin,
|
||||
.update_plane = mixer_update_plane,
|
||||
.disable_plane = mixer_disable_plane,
|
||||
@ -1155,18 +1123,6 @@ static struct mixer_drv_data exynos4210_mxr_drv_data = {
|
||||
.has_sclk = 1,
|
||||
};
|
||||
|
||||
static const struct platform_device_id mixer_driver_types[] = {
|
||||
{
|
||||
.name = "s5p-mixer",
|
||||
.driver_data = (unsigned long)&exynos4210_mxr_drv_data,
|
||||
}, {
|
||||
.name = "exynos5-mixer",
|
||||
.driver_data = (unsigned long)&exynos5250_mxr_drv_data,
|
||||
}, {
|
||||
/* end node */
|
||||
}
|
||||
};
|
||||
|
||||
static struct of_device_id mixer_match_types[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos4210-mixer",
|
||||
@ -1243,7 +1199,7 @@ static const struct component_ops mixer_component_ops = {
|
||||
static int mixer_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mixer_drv_data *drv;
|
||||
const struct mixer_drv_data *drv;
|
||||
struct mixer_context *ctx;
|
||||
int ret;
|
||||
|
||||
@ -1253,23 +1209,13 @@ static int mixer_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (dev->of_node) {
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_node(mixer_match_types, dev->of_node);
|
||||
drv = (struct mixer_drv_data *)match->data;
|
||||
} else {
|
||||
drv = (struct mixer_drv_data *)
|
||||
platform_get_device_id(pdev)->driver_data;
|
||||
}
|
||||
drv = of_device_get_match_data(dev);
|
||||
|
||||
ctx->pdev = pdev;
|
||||
ctx->dev = dev;
|
||||
ctx->vp_enabled = drv->is_vp_enabled;
|
||||
ctx->has_sclk = drv->has_sclk;
|
||||
ctx->mxr_ver = drv->version;
|
||||
init_waitqueue_head(&ctx->wait_vsync_queue);
|
||||
atomic_set(&ctx->wait_vsync_event, 0);
|
||||
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
|
||||
@ -1355,5 +1301,4 @@ struct platform_driver mixer_driver = {
|
||||
},
|
||||
.probe = mixer_probe,
|
||||
.remove = mixer_remove,
|
||||
.id_table = mixer_driver_types,
|
||||
};
|
||||
|
@ -586,10 +586,12 @@
|
||||
#define HDMI_TG_VACT_ST4_L HDMI_TG_BASE(0x0070)
|
||||
#define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074)
|
||||
#define HDMI_TG_3D HDMI_TG_BASE(0x00F0)
|
||||
#define HDMI_TG_DECON_EN HDMI_TG_BASE(0x01e0)
|
||||
|
||||
/* HDMI PHY Registers Offsets*/
|
||||
#define HDMIPHY_POWER (0x74 >> 2)
|
||||
#define HDMIPHY_MODE_SET_DONE (0x7c >> 2)
|
||||
#define HDMIPHY_POWER 0x74
|
||||
#define HDMIPHY_MODE_SET_DONE 0x7c
|
||||
#define HDMIPHY5433_MODE_SET_DONE 0x84
|
||||
|
||||
/* HDMI PHY Values */
|
||||
#define HDMI_PHY_POWER_ON 0x80
|
||||
@ -603,4 +605,7 @@
|
||||
#define PMU_HDMI_PHY_CONTROL 0x700
|
||||
#define PMU_HDMI_PHY_ENABLE_BIT BIT(0)
|
||||
|
||||
#define EXYNOS5433_SYSREG_DISP_HDMI_PHY 0x1008
|
||||
#define SYSREG_HDMI_REFCLK_INT_CLK 1
|
||||
|
||||
#endif /* SAMSUNG_REGS_HDMI_H */
|
||||
|
@ -179,9 +179,9 @@
|
||||
#define TRIGCON_TRIGMODE_W1BUF (1 << 10)
|
||||
#define TRIGCON_SWTRIGCMD_W0BUF (1 << 6)
|
||||
#define TRIGCON_TRIGMODE_W0BUF (1 << 5)
|
||||
#define TRIGCON_HWTRIGMASK_I80_RGB (1 << 4)
|
||||
#define TRIGCON_HWTRIGEN_I80_RGB (1 << 3)
|
||||
#define TRIGCON_HWTRIG_INV_I80_RGB (1 << 2)
|
||||
#define TRIGCON_HWTRIGMASK (1 << 4)
|
||||
#define TRIGCON_HWTRIGEN (1 << 3)
|
||||
#define TRIGCON_HWTRIG_INV (1 << 2)
|
||||
#define TRIGCON_SWTRIGCMD (1 << 1)
|
||||
#define TRIGCON_SWTRIGEN (1 << 0)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user