2015-10-29 11:36:23 +03:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 Free Electrons
|
|
|
|
* Copyright (C) 2015 NextThing Co
|
|
|
|
*
|
|
|
|
* Boris Brezillon <boris.brezillon@free-electrons.com>
|
|
|
|
* Maxime Ripard <maxime.ripard@free-electrons.com>
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __SUN4I_TCON_H__
|
|
|
|
#define __SUN4I_TCON_H__
|
|
|
|
|
|
|
|
#include <drm/drm_crtc.h>
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
2017-04-21 11:38:50 +03:00
|
|
|
#include <linux/list.h>
|
2015-10-29 11:36:23 +03:00
|
|
|
#include <linux/reset.h>
|
|
|
|
|
|
|
|
#define SUN4I_TCON_GCTL_REG 0x0
|
|
|
|
#define SUN4I_TCON_GCTL_TCON_ENABLE BIT(31)
|
|
|
|
#define SUN4I_TCON_GCTL_IOMAP_MASK BIT(0)
|
|
|
|
#define SUN4I_TCON_GCTL_IOMAP_TCON1 (1 << 0)
|
|
|
|
#define SUN4I_TCON_GCTL_IOMAP_TCON0 (0 << 0)
|
|
|
|
|
|
|
|
#define SUN4I_TCON_GINT0_REG 0x4
|
|
|
|
#define SUN4I_TCON_GINT0_VBLANK_ENABLE(pipe) BIT(31 - (pipe))
|
|
|
|
#define SUN4I_TCON_GINT0_VBLANK_INT(pipe) BIT(15 - (pipe))
|
|
|
|
|
|
|
|
#define SUN4I_TCON_GINT1_REG 0x8
|
|
|
|
#define SUN4I_TCON_FRM_CTL_REG 0x10
|
|
|
|
|
|
|
|
#define SUN4I_TCON0_CTL_REG 0x40
|
|
|
|
#define SUN4I_TCON0_CTL_TCON_ENABLE BIT(31)
|
|
|
|
#define SUN4I_TCON0_CTL_CLK_DELAY_MASK GENMASK(8, 4)
|
|
|
|
#define SUN4I_TCON0_CTL_CLK_DELAY(delay) ((delay << 4) & SUN4I_TCON0_CTL_CLK_DELAY_MASK)
|
2017-09-08 10:50:14 +03:00
|
|
|
#define SUN4I_TCON0_CTL_SRC_SEL_MASK GENMASK(2, 0)
|
2015-10-29 11:36:23 +03:00
|
|
|
|
|
|
|
#define SUN4I_TCON0_DCLK_REG 0x44
|
|
|
|
#define SUN4I_TCON0_DCLK_GATE_BIT (31)
|
|
|
|
#define SUN4I_TCON0_DCLK_DIV_SHIFT (0)
|
|
|
|
#define SUN4I_TCON0_DCLK_DIV_WIDTH (7)
|
|
|
|
|
|
|
|
#define SUN4I_TCON0_BASIC0_REG 0x48
|
|
|
|
#define SUN4I_TCON0_BASIC0_X(width) ((((width) - 1) & 0xfff) << 16)
|
|
|
|
#define SUN4I_TCON0_BASIC0_Y(height) (((height) - 1) & 0xfff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON0_BASIC1_REG 0x4c
|
|
|
|
#define SUN4I_TCON0_BASIC1_H_TOTAL(total) ((((total) - 1) & 0x1fff) << 16)
|
|
|
|
#define SUN4I_TCON0_BASIC1_H_BACKPORCH(bp) (((bp) - 1) & 0xfff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON0_BASIC2_REG 0x50
|
2017-05-27 19:09:30 +03:00
|
|
|
#define SUN4I_TCON0_BASIC2_V_TOTAL(total) (((total) & 0x1fff) << 16)
|
2015-10-29 11:36:23 +03:00
|
|
|
#define SUN4I_TCON0_BASIC2_V_BACKPORCH(bp) (((bp) - 1) & 0xfff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON0_BASIC3_REG 0x54
|
|
|
|
#define SUN4I_TCON0_BASIC3_H_SYNC(width) ((((width) - 1) & 0x7ff) << 16)
|
|
|
|
#define SUN4I_TCON0_BASIC3_V_SYNC(height) (((height) - 1) & 0x7ff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON0_HV_IF_REG 0x58
|
|
|
|
#define SUN4I_TCON0_CPU_IF_REG 0x60
|
|
|
|
#define SUN4I_TCON0_CPU_WR_REG 0x64
|
|
|
|
#define SUN4I_TCON0_CPU_RD0_REG 0x68
|
|
|
|
#define SUN4I_TCON0_CPU_RDA_REG 0x6c
|
|
|
|
#define SUN4I_TCON0_TTL0_REG 0x70
|
|
|
|
#define SUN4I_TCON0_TTL1_REG 0x74
|
|
|
|
#define SUN4I_TCON0_TTL2_REG 0x78
|
|
|
|
#define SUN4I_TCON0_TTL3_REG 0x7c
|
|
|
|
#define SUN4I_TCON0_TTL4_REG 0x80
|
|
|
|
#define SUN4I_TCON0_LVDS_IF_REG 0x84
|
|
|
|
#define SUN4I_TCON0_IO_POL_REG 0x88
|
|
|
|
#define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase) ((phase & 3) << 28)
|
|
|
|
#define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE BIT(25)
|
|
|
|
#define SUN4I_TCON0_IO_POL_VSYNC_POSITIVE BIT(24)
|
|
|
|
|
|
|
|
#define SUN4I_TCON0_IO_TRI_REG 0x8c
|
|
|
|
#define SUN4I_TCON0_IO_TRI_HSYNC_DISABLE BIT(25)
|
|
|
|
#define SUN4I_TCON0_IO_TRI_VSYNC_DISABLE BIT(24)
|
|
|
|
#define SUN4I_TCON0_IO_TRI_DATA_PINS_DISABLE(pins) GENMASK(pins, 0)
|
|
|
|
|
|
|
|
#define SUN4I_TCON1_CTL_REG 0x90
|
|
|
|
#define SUN4I_TCON1_CTL_TCON_ENABLE BIT(31)
|
|
|
|
#define SUN4I_TCON1_CTL_INTERLACE_ENABLE BIT(20)
|
|
|
|
#define SUN4I_TCON1_CTL_CLK_DELAY_MASK GENMASK(8, 4)
|
|
|
|
#define SUN4I_TCON1_CTL_CLK_DELAY(delay) ((delay << 4) & SUN4I_TCON1_CTL_CLK_DELAY_MASK)
|
2017-09-08 10:50:14 +03:00
|
|
|
#define SUN4I_TCON1_CTL_SRC_SEL_MASK GENMASK(1, 0)
|
2015-10-29 11:36:23 +03:00
|
|
|
|
|
|
|
#define SUN4I_TCON1_BASIC0_REG 0x94
|
|
|
|
#define SUN4I_TCON1_BASIC0_X(width) ((((width) - 1) & 0xfff) << 16)
|
|
|
|
#define SUN4I_TCON1_BASIC0_Y(height) (((height) - 1) & 0xfff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON1_BASIC1_REG 0x98
|
|
|
|
#define SUN4I_TCON1_BASIC1_X(width) ((((width) - 1) & 0xfff) << 16)
|
|
|
|
#define SUN4I_TCON1_BASIC1_Y(height) (((height) - 1) & 0xfff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON1_BASIC2_REG 0x9c
|
|
|
|
#define SUN4I_TCON1_BASIC2_X(width) ((((width) - 1) & 0xfff) << 16)
|
|
|
|
#define SUN4I_TCON1_BASIC2_Y(height) (((height) - 1) & 0xfff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON1_BASIC3_REG 0xa0
|
|
|
|
#define SUN4I_TCON1_BASIC3_H_TOTAL(total) ((((total) - 1) & 0x1fff) << 16)
|
|
|
|
#define SUN4I_TCON1_BASIC3_H_BACKPORCH(bp) (((bp) - 1) & 0xfff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON1_BASIC4_REG 0xa4
|
|
|
|
#define SUN4I_TCON1_BASIC4_V_TOTAL(total) (((total) & 0x1fff) << 16)
|
|
|
|
#define SUN4I_TCON1_BASIC4_V_BACKPORCH(bp) (((bp) - 1) & 0xfff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON1_BASIC5_REG 0xa8
|
|
|
|
#define SUN4I_TCON1_BASIC5_H_SYNC(width) ((((width) - 1) & 0x3ff) << 16)
|
|
|
|
#define SUN4I_TCON1_BASIC5_V_SYNC(height) (((height) - 1) & 0x3ff)
|
|
|
|
|
|
|
|
#define SUN4I_TCON1_IO_POL_REG 0xf0
|
|
|
|
#define SUN4I_TCON1_IO_TRI_REG 0xf4
|
|
|
|
#define SUN4I_TCON_CEU_CTL_REG 0x100
|
|
|
|
#define SUN4I_TCON_CEU_MUL_RR_REG 0x110
|
|
|
|
#define SUN4I_TCON_CEU_MUL_RG_REG 0x114
|
|
|
|
#define SUN4I_TCON_CEU_MUL_RB_REG 0x118
|
|
|
|
#define SUN4I_TCON_CEU_ADD_RC_REG 0x11c
|
|
|
|
#define SUN4I_TCON_CEU_MUL_GR_REG 0x120
|
|
|
|
#define SUN4I_TCON_CEU_MUL_GG_REG 0x124
|
|
|
|
#define SUN4I_TCON_CEU_MUL_GB_REG 0x128
|
|
|
|
#define SUN4I_TCON_CEU_ADD_GC_REG 0x12c
|
|
|
|
#define SUN4I_TCON_CEU_MUL_BR_REG 0x130
|
|
|
|
#define SUN4I_TCON_CEU_MUL_BG_REG 0x134
|
|
|
|
#define SUN4I_TCON_CEU_MUL_BB_REG 0x138
|
|
|
|
#define SUN4I_TCON_CEU_ADD_BC_REG 0x13c
|
|
|
|
#define SUN4I_TCON_CEU_RANGE_R_REG 0x140
|
|
|
|
#define SUN4I_TCON_CEU_RANGE_G_REG 0x144
|
|
|
|
#define SUN4I_TCON_CEU_RANGE_B_REG 0x148
|
|
|
|
#define SUN4I_TCON_MUX_CTRL_REG 0x200
|
|
|
|
#define SUN4I_TCON1_FILL_CTL_REG 0x300
|
|
|
|
#define SUN4I_TCON1_FILL_BEG0_REG 0x304
|
|
|
|
#define SUN4I_TCON1_FILL_END0_REG 0x308
|
|
|
|
#define SUN4I_TCON1_FILL_DATA0_REG 0x30c
|
|
|
|
#define SUN4I_TCON1_FILL_BEG1_REG 0x310
|
|
|
|
#define SUN4I_TCON1_FILL_END1_REG 0x314
|
|
|
|
#define SUN4I_TCON1_FILL_DATA1_REG 0x318
|
|
|
|
#define SUN4I_TCON1_FILL_BEG2_REG 0x31c
|
|
|
|
#define SUN4I_TCON1_FILL_END2_REG 0x320
|
|
|
|
#define SUN4I_TCON1_FILL_DATA2_REG 0x324
|
|
|
|
#define SUN4I_TCON1_GAMMA_TABLE_REG 0x400
|
|
|
|
|
|
|
|
#define SUN4I_TCON_MAX_CHANNELS 2
|
|
|
|
|
2017-10-10 06:19:58 +03:00
|
|
|
struct sun4i_tcon;
|
|
|
|
|
2016-10-20 06:43:39 +03:00
|
|
|
struct sun4i_tcon_quirks {
|
|
|
|
bool has_channel_1; /* a33 does not have channel 1 */
|
2017-09-08 10:50:14 +03:00
|
|
|
bool needs_de_be_mux; /* sun6i needs mux to select backend */
|
2017-10-10 06:19:58 +03:00
|
|
|
|
|
|
|
/* callback to handle tcon muxing options */
|
2017-10-17 12:06:10 +03:00
|
|
|
int (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
|
2016-10-20 06:43:39 +03:00
|
|
|
};
|
|
|
|
|
2015-10-29 11:36:23 +03:00
|
|
|
struct sun4i_tcon {
|
2016-07-19 16:17:27 +03:00
|
|
|
struct device *dev;
|
2015-10-29 11:36:23 +03:00
|
|
|
struct drm_device *drm;
|
|
|
|
struct regmap *regs;
|
|
|
|
|
|
|
|
/* Main bus clock */
|
|
|
|
struct clk *clk;
|
|
|
|
|
|
|
|
/* Clocks for the TCON channels */
|
|
|
|
struct clk *sclk0;
|
|
|
|
struct clk *sclk1;
|
|
|
|
|
|
|
|
/* Pixel clock */
|
|
|
|
struct clk *dclk;
|
|
|
|
|
|
|
|
/* Reset control */
|
|
|
|
struct reset_control *lcd_rst;
|
|
|
|
|
2015-10-29 11:37:32 +03:00
|
|
|
struct drm_panel *panel;
|
2016-01-07 14:32:07 +03:00
|
|
|
|
2016-10-20 06:43:39 +03:00
|
|
|
/* Platform adjustments */
|
|
|
|
const struct sun4i_tcon_quirks *quirks;
|
drm/sun4i: Initialize crtc from tcon bind function
The tcon provides part of the functionality of the crtc, and also
provides the device node for the output port of the crtc. To be able
to use drm_of_find_possible_crtcs(), all crtc must be initialized before
any downstream encoders. The other part of the crtc is the display
backend.
The Rockchip DRM driver does this by first binding all vops, which is
their crtc, and this step also creates the crtc objects. Then all
remaining hardware components are bound. With the Allwinner display
pipeline, we have multiple components comprising the crtc, and varying
depths of the display pipeline. Since components are added with a depth
first search of the of_graph, we can initialize the crtc object within
the tcon bind function. Since the backend precedes the tcon, and the
backends cannot be muxed or switched around, we can be sure that the
associated backend is already initialized.
This patch also moves the crtc pointer from the main drm_device data to
the tcon device data. Besides the crtc callbacks, the crtc structure is
only used within the tcon driver to signal vblank events from its
interrupt handler.
As the crtc and layer bits are now called from the tcon bits, we must
move them from the sun4i-drm module to the sun4i-tcon module to avoid
circular dependencies between the two modules. This is because sun4i-drm
also calls into sun4i-tcon.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
2017-02-23 11:05:37 +03:00
|
|
|
|
|
|
|
/* Associated crtc */
|
|
|
|
struct sun4i_crtc *crtc;
|
2017-04-21 11:38:50 +03:00
|
|
|
|
2017-04-21 11:38:55 +03:00
|
|
|
int id;
|
|
|
|
|
2017-04-21 11:38:50 +03:00
|
|
|
/* TCON list management */
|
|
|
|
struct list_head list;
|
2015-10-29 11:36:23 +03:00
|
|
|
};
|
|
|
|
|
2016-04-11 13:16:33 +03:00
|
|
|
struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
|
2016-07-20 11:35:06 +03:00
|
|
|
struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
|
|
|
|
|
2015-10-29 11:36:23 +03:00
|
|
|
void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
|
drm/sun4i: tcon: Don't rely on encoders to enable the TCON
So far, we've required all the TCON-connected encoders to call the TCON
enable and disable functions.
This was made this way because in the RGB/LVDS case, the TCON is the CRTC
and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
have another encoder down the road that needs to be programmed.
We also needed to know which channel the encoder is connected to, which is
encoder-specific.
The CRTC's enable and disable callbacks can work just fine for our use
case, and we can get the channel to use just by looking at the type of
encoder, since that is fixed. Implement those callbacks, which will
remove some of the encoder boilerplate.
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Link: https://patchwork.freedesktop.org/patch/msgid/90b4396e19b3eca61b2ebfdae0672074b88ad74d.1508231063.git-series.maxime.ripard@free-electrons.com
2017-10-17 12:06:12 +03:00
|
|
|
void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
|
|
|
|
const struct drm_encoder *encoder, bool enable);
|
2015-10-29 11:36:23 +03:00
|
|
|
|
|
|
|
/* Mode Related Controls */
|
2017-05-27 19:09:27 +03:00
|
|
|
void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
|
|
|
|
struct drm_encoder *encoder);
|
2015-10-29 11:36:23 +03:00
|
|
|
void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
|
|
|
|
struct drm_display_mode *mode);
|
|
|
|
void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
|
|
|
|
struct drm_display_mode *mode);
|
|
|
|
|
|
|
|
#endif /* __SUN4I_TCON_H__ */
|