Skip to content

Commit

Permalink
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  ...
  • Loading branch information
Dave Airlie committed May 4, 2016
2 parents acff058 + b5bf0f1 commit 00c1bea
Show file tree
Hide file tree
Showing 22 changed files with 572 additions and 623 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
27 changes: 24 additions & 3 deletions Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ 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.
- hpd-gpio: following information about the hotplug gpio pin.
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.
Expand All @@ -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:

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/exynos/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
86 changes: 44 additions & 42 deletions drivers/gpu/drm/exynos/exynos5433_drm_decon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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,
Expand All @@ -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;
};

Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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;
Expand All @@ -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(
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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)
Expand All @@ -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);
}

Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -617,19 +620,18 @@ 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)
},
{},
};
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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/exynos/exynos7_drm_decon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 3 additions & 6 deletions drivers/gpu/drm/exynos/exynos_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/exynos_drm_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading

0 comments on commit 00c1bea

Please sign in to comment.