Skip to content

Commit

Permalink
Merge branch 'drm-next-4.12' of https://github.com/ckhu-mediatek/linu…
Browse files Browse the repository at this point in the history
…x.git-tags into drm-next

This series is MT2701 DRM support.

* 'drm-next-4.12' of https://github.com/ckhu-mediatek/linux.git-tags:
  drm/mediatek: add support for Mediatek SoC MT2701
  drm/mediatek: update DSI sub driver flow for sending commands to panel
  drm/mediatek: add non-continuous clock mode and EOT packet control
  drm/mediatek: add dsi transfer function
  drm/mediatek: add dsi interrupt control
  drm/mediatek: cleaning up and refine
  drm/mediatek: update display module connections
  drm/mediatek: add BLS component
  drm/mediatek: add shadow register support
  drm/mediatek: add *driver_data for different hardware settings
  drm/mediatek: add helpers for coverting from the generic components
  dt-bindings: display: mediatek: update supported chips
  • Loading branch information
Dave Airlie committed Apr 10, 2017
2 parents 0168778 + 84a5ead commit cdf5316
Show file tree
Hide file tree
Showing 13 changed files with 828 additions and 238 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Required properties (all function blocks):
"mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt
"mediatek,<chip>-disp-mutex" - display mutex
"mediatek,<chip>-disp-od" - overdrive
the supported chips are mt2701 and mt8173.
- reg: Physical base address and length of the function block register space
- interrupts: The interrupt signal from the function block (required, except for
merge and split function blocks).
Expand All @@ -54,6 +55,7 @@ Required properties (DMA function blocks):
"mediatek,<chip>-disp-ovl"
"mediatek,<chip>-disp-rdma"
"mediatek,<chip>-disp-wdma"
the supported chips are mt2701 and mt8173.
- larb: Should contain a phandle pointing to the local arbiter device as defined
in Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
- iommus: Should point to the respective IOMMU block with master port as
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ channel output.

Required properties:
- compatible: "mediatek,<chip>-dsi"
the supported chips are mt2701 and mt8173.
- reg: Physical base address and length of the controller's registers
- interrupts: The interrupt signal from the function block.
- clocks: device clocks
Expand All @@ -25,6 +26,7 @@ The MIPI TX configuration module controls the MIPI D-PHY.

Required properties:
- compatible: "mediatek,<chip>-mipi-tx"
the supported chips are mt2701 and mt8173.
- reg: Physical base address and length of the controller's registers
- clocks: PLL reference clock
- clock-output-names: name of the output clock line to the DSI encoder
Expand Down
64 changes: 47 additions & 17 deletions drivers/gpu/drm/mediatek/mtk_disp_ovl.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,28 @@
#define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n))
#define DISP_REG_OVL_ADDR(n) (0x0f40 + 0x20 * (n))
#define DISP_REG_OVL_ADDR_MT2701 0x0040
#define DISP_REG_OVL_ADDR_MT8173 0x0f40
#define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n))

#define OVL_RDMA_MEM_GMC 0x40402020

#define OVL_CON_BYTE_SWAP BIT(24)
#define OVL_CON_CLRFMT_RGB565 (0 << 12)
#define OVL_CON_CLRFMT_RGB888 (1 << 12)
#define OVL_CON_CLRFMT_RGB (1 << 12)
#define OVL_CON_CLRFMT_RGBA8888 (2 << 12)
#define OVL_CON_CLRFMT_ARGB8888 (3 << 12)
#define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
0 : OVL_CON_CLRFMT_RGB)
#define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
OVL_CON_CLRFMT_RGB : 0)
#define OVL_CON_AEN BIT(8)
#define OVL_CON_ALPHA 0xff

struct mtk_disp_ovl_data {
unsigned int addr;
bool fmt_rgb565_is_0;
};

/**
* struct mtk_disp_ovl - DISP_OVL driver structure
* @ddp_comp - structure containing type enum and hardware resources
Expand All @@ -55,8 +65,14 @@
struct mtk_disp_ovl {
struct mtk_ddp_comp ddp_comp;
struct drm_crtc *crtc;
const struct mtk_disp_ovl_data *data;
};

static inline struct mtk_disp_ovl *comp_to_ovl(struct mtk_ddp_comp *comp)
{
return container_of(comp, struct mtk_disp_ovl, ddp_comp);
}

static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
{
struct mtk_disp_ovl *priv = dev_id;
Expand All @@ -76,20 +92,18 @@ static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp,
struct drm_crtc *crtc)
{
struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl,
ddp_comp);
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);

priv->crtc = crtc;
ovl->crtc = crtc;
writel(0x0, comp->regs + DISP_REG_OVL_INTSTA);
writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN);
}

static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp)
{
struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl,
ddp_comp);
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);

priv->crtc = NULL;
ovl->crtc = NULL;
writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN);
}

Expand Down Expand Up @@ -138,18 +152,18 @@ static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx)
writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
}

static unsigned int ovl_fmt_convert(unsigned int fmt)
static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
{
switch (fmt) {
default:
case DRM_FORMAT_RGB565:
return OVL_CON_CLRFMT_RGB565;
return OVL_CON_CLRFMT_RGB565(ovl);
case DRM_FORMAT_BGR565:
return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP;
return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
case DRM_FORMAT_RGB888:
return OVL_CON_CLRFMT_RGB888;
return OVL_CON_CLRFMT_RGB888(ovl);
case DRM_FORMAT_BGR888:
return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP;
return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_RGBA8888:
return OVL_CON_CLRFMT_ARGB8888;
Expand All @@ -168,6 +182,7 @@ static unsigned int ovl_fmt_convert(unsigned int fmt)
static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
struct mtk_plane_state *state)
{
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
struct mtk_plane_pending_state *pending = &state->pending;
unsigned int addr = pending->addr;
unsigned int pitch = pending->pitch & 0xffff;
Expand All @@ -179,15 +194,15 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
if (!pending->enable)
mtk_ovl_layer_off(comp, idx);

con = ovl_fmt_convert(fmt);
con = ovl_fmt_convert(ovl, fmt);
if (idx != 0)
con |= OVL_CON_AEN | OVL_CON_ALPHA;

writel_relaxed(con, comp->regs + DISP_REG_OVL_CON(idx));
writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx));
writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx));
writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(ovl, idx));

if (pending->enable)
mtk_ovl_layer_on(comp, idx);
Expand Down Expand Up @@ -264,6 +279,8 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return ret;
}

priv->data = of_device_get_match_data(dev);

platform_set_drvdata(pdev, priv);

ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
Expand All @@ -287,8 +304,21 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
return 0;
}

static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
.addr = DISP_REG_OVL_ADDR_MT2701,
.fmt_rgb565_is_0 = false,
};

static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
.addr = DISP_REG_OVL_ADDR_MT8173,
.fmt_rgb565_is_0 = true,
};

static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
{ .compatible = "mediatek,mt8173-disp-ovl", },
{ .compatible = "mediatek,mt2701-disp-ovl",
.data = &mt2701_ovl_driver_data},
{ .compatible = "mediatek,mt8173-disp-ovl",
.data = &mt8173_ovl_driver_data},
{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
Expand Down
39 changes: 31 additions & 8 deletions drivers/gpu/drm/mediatek/mtk_disp_rdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
#define RDMA_FIFO_UNDERFLOW_EN BIT(31)
#define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16)
#define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16)
#define RDMA_FIFO_SIZE(rdma) ((rdma)->data->fifo_size)

struct mtk_disp_rdma_data {
unsigned int fifo_size;
};

/**
* struct mtk_disp_rdma - DISP_RDMA driver structure
Expand All @@ -47,8 +52,14 @@
struct mtk_disp_rdma {
struct mtk_ddp_comp ddp_comp;
struct drm_crtc *crtc;
const struct mtk_disp_rdma_data *data;
};

static inline struct mtk_disp_rdma *comp_to_rdma(struct mtk_ddp_comp *comp)
{
return container_of(comp, struct mtk_disp_rdma, ddp_comp);
}

static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id)
{
struct mtk_disp_rdma *priv = dev_id;
Expand Down Expand Up @@ -77,20 +88,18 @@ static void rdma_update_bits(struct mtk_ddp_comp *comp, unsigned int reg,
static void mtk_rdma_enable_vblank(struct mtk_ddp_comp *comp,
struct drm_crtc *crtc)
{
struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma,
ddp_comp);
struct mtk_disp_rdma *rdma = comp_to_rdma(comp);

priv->crtc = crtc;
rdma->crtc = crtc;
rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
RDMA_FRAME_END_INT);
}

static void mtk_rdma_disable_vblank(struct mtk_ddp_comp *comp)
{
struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma,
ddp_comp);
struct mtk_disp_rdma *rdma = comp_to_rdma(comp);

priv->crtc = NULL;
rdma->crtc = NULL;
rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
}

Expand All @@ -111,6 +120,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
{
unsigned int threshold;
unsigned int reg;
struct mtk_disp_rdma *rdma = comp_to_rdma(comp);

rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, 0xfff, width);
rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_1, 0xfffff, height);
Expand All @@ -123,7 +133,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
*/
threshold = width * height * vrefresh * 4 * 7 / 1000000;
reg = RDMA_FIFO_UNDERFLOW_EN |
RDMA_FIFO_PSEUDO_SIZE(SZ_8K) |
RDMA_FIFO_PSEUDO_SIZE(RDMA_FIFO_SIZE(rdma)) |
RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON);
}
Expand Down Expand Up @@ -208,6 +218,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
return ret;
}

priv->data = of_device_get_match_data(dev);

platform_set_drvdata(pdev, priv);

ret = component_add(dev, &mtk_disp_rdma_component_ops);
Expand All @@ -224,8 +236,19 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
return 0;
}

static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = {
.fifo_size = SZ_4K,
};

static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = {
.fifo_size = SZ_8K,
};

static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
{ .compatible = "mediatek,mt8173-disp-rdma", },
{ .compatible = "mediatek,mt2701-disp-rdma",
.data = &mt2701_rdma_driver_data},
{ .compatible = "mediatek,mt8173-disp-rdma",
.data = &mt8173_rdma_driver_data},
{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
Expand Down
75 changes: 46 additions & 29 deletions drivers/gpu/drm/mediatek/mtk_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,42 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
pm_runtime_put(drm->dev);
}

static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
unsigned int i;

/*
* TODO: instead of updating the registers here, we should prepare
* working registers in atomic_commit and let the hardware command
* queue update module registers on vblank.
*/
if (state->pending_config) {
mtk_ddp_comp_config(ovl, state->pending_width,
state->pending_height,
state->pending_vrefresh, 0);

state->pending_config = false;
}

if (mtk_crtc->pending_planes) {
for (i = 0; i < OVL_LAYER_NR; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
struct mtk_plane_state *plane_state;

plane_state = to_mtk_plane_state(plane->state);

if (plane_state->pending.config) {
mtk_ddp_comp_layer_config(ovl, i, plane_state);
plane_state->pending.config = false;
}
}
mtk_crtc->pending_planes = false;
}
}

static void mtk_drm_crtc_enable(struct drm_crtc *crtc)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
Expand Down Expand Up @@ -403,6 +439,7 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_drm_private *priv = crtc->dev->dev_private;
unsigned int pending_planes = 0;
int i;

Expand All @@ -424,6 +461,12 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
if (crtc->state->color_mgmt_changed)
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);

if (priv->data->shadow_register) {
mtk_disp_mutex_acquire(mtk_crtc->mutex);
mtk_crtc_ddp_config(crtc);
mtk_disp_mutex_release(mtk_crtc->mutex);
}
}

static const struct drm_crtc_funcs mtk_crtc_funcs = {
Expand Down Expand Up @@ -471,36 +514,10 @@ static int mtk_drm_crtc_init(struct drm_device *drm,
void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
unsigned int i;
struct mtk_drm_private *priv = crtc->dev->dev_private;

/*
* TODO: instead of updating the registers here, we should prepare
* working registers in atomic_commit and let the hardware command
* queue update module registers on vblank.
*/
if (state->pending_config) {
mtk_ddp_comp_config(ovl, state->pending_width,
state->pending_height,
state->pending_vrefresh, 0);

state->pending_config = false;
}

if (mtk_crtc->pending_planes) {
for (i = 0; i < OVL_LAYER_NR; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
struct mtk_plane_state *plane_state;

plane_state = to_mtk_plane_state(plane->state);

if (plane_state->pending.config) {
mtk_ddp_comp_layer_config(ovl, i, plane_state);
plane_state->pending.config = false;
}
}
mtk_crtc->pending_planes = false;
}
if (!priv->data->shadow_register)
mtk_crtc_ddp_config(crtc);

mtk_drm_finish_page_flip(mtk_crtc);
}
Expand Down
Loading

0 comments on commit cdf5316

Please sign in to comment.