Skip to content

Commit

Permalink
Merge pull request torvalds#165 from xin3liang/hikey-test
Browse files Browse the repository at this point in the history
Fixes for bug torvalds#136 and torvalds#82
  • Loading branch information
docularxu committed Dec 16, 2015
2 parents d4e05b7 + e969adb commit c3e766c
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 8 deletions.
8 changes: 6 additions & 2 deletions arch/arm64/boot/dts/hi6220.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -742,9 +742,12 @@
ade: ade@f4100000 {
compatible = "hisilicon,hi6220-ade";
reg = <0x0 0xf4100000 0x0 0x7800>,
<0x0 0xf4410000 0x0 0x1000>;
<0x0 0xf4410000 0x0 0x1000>,
<0x0 0xf4520000 0x0 0x1000>;
reg-names = "ade_base",
"media_base";
"media_base",
"media_noc_base";

clocks = <&clock_media HI6220_ADE_CORE>,
<&clock_media HI6220_CODEC_JPEG>,
<&clock_media HI6220_ADE_PIX_SRC>,
Expand All @@ -756,6 +759,7 @@
"clk_ade_pix",
"clk_syspll_src",
"clk_medpll_src";
interrupts = <0 114 4>, <0 115 4>;
/*ade core clock rate*/
ade_core_clk_rate = <360000000>;
/*media_noc clock rate*/
Expand Down
8 changes: 8 additions & 0 deletions drivers/gpu/drm/hisilicon/hisi_ade_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,17 @@
#define ADE_OVLY1_TRANS_CFG_REG (0x2C)
#define ADE_CTRAN5_TRANS_CFG_REG (0x40)
#define ADE_EN_REG (0x100)
#define INTR_INIT_STATE_CPU_0_REG (0xC00)
#define INTR_INIT_STATE_CPU_1_REG (0xC04)
#define INTR_MASK_STATE_CPU_0_REG (0xC08)
#define INTR_MASK_STATE_CPU_1_REG (0xC0C)
#define INTR_MASK_CPU_0_REG (0xC10)
#define INTR_MASK_CPU_1_REG (0xC14)
#define INTR_CLEAR_CPU_0_REG (0xC18)
#define INTR_CLEAR_CPU_1_REG (0xC1C)
#define ADE_FRM_DISGARD_CTRL_REG (0xA4)
#define ADE_SOFT_RST0_REG (0x70)
#define ADE_SOFT_RST1_REG (0x74)
#define ADE_SOFT_RST_SEL0_REG (0x78)
#define ADE_SOFT_RST_SEL1_REG (0x7C)
#define ADE_RELOAD_DIS0_REG (0xAC)
Expand Down
123 changes: 120 additions & 3 deletions drivers/gpu/drm/hisilicon/hisi_drm_ade.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@

#define SC_MEDIA_RSTDIS (0x530)
#define SC_MEDIA_RSTEN (0x52C)
#define NOC_ADE0_QOSGENERATOR_MODE 0x010C
#define NOC_ADE0_QOSGENERATOR_EXTCONTROL 0x0118
#define NOC_ADE1_QOSGENERATOR_MODE 0x020C
#define NOC_ADE1_QOSGENERATOR_EXTCONTROL 0x0218

enum {
LDI_TEST = 0,
Expand Down Expand Up @@ -98,6 +102,7 @@ struct hisi_drm_ade_crtc {
bool enable;
u8 __iomem *ade_base;
u8 __iomem *media_base;
void __iomem *media_noc_base;
u32 ade_core_rate;
u32 media_noc_rate;
u32 x , y;
Expand All @@ -110,13 +115,37 @@ struct hisi_drm_ade_crtc {
struct clk *media_noc_clk;
struct clk *ade_pix_clk;
bool power_on;

u32 res_switch_cmpl;
wait_queue_head_t wait_res_cmpl;
};

static int hisi_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb);
static void ldi_init(struct hisi_drm_ade_crtc *crtc_ade);

void ade_set_medianoc_qos(struct hisi_drm_ade_crtc *crtc_ade)
{
void __iomem *base = crtc_ade->media_noc_base;
void __iomem *reg;
u32 val;

reg = base + NOC_ADE0_QOSGENERATOR_MODE;
val = (readl(reg) & 0xfffffffc) | 0x2;
writel(val, reg);

reg = base + NOC_ADE0_QOSGENERATOR_EXTCONTROL;
val = readl(reg) | 0x1;
writel(val, reg);

reg = base + NOC_ADE1_QOSGENERATOR_MODE;
val = (readl(reg) & 0xfffffffc) | 0x2;
writel(val, reg);

reg = base + NOC_ADE1_QOSGENERATOR_EXTCONTROL;
val = readl(reg) | 0x1;
writel(val, reg);
}

static void ade_init(struct hisi_drm_ade_crtc *crtc_ade)
{
u8 __iomem *ade_base = crtc_ade->ade_base;
Expand All @@ -128,7 +157,6 @@ static void ade_init(struct hisi_drm_ade_crtc *crtc_ade)

writel(cpu0_mask, ade_base + INTR_MASK_CPU_0_REG);
writel(cpu1_mask, ade_base + INTR_MASK_CPU_1_REG);
set_TOP_CTL_frm_end_start(ade_base, 2);

/* disable wdma2 and wdma3 frame discard */
writel(0x0, ade_base + ADE_FRM_DISGARD_CTRL_REG);
Expand Down Expand Up @@ -204,6 +232,7 @@ static int hisi_drm_crtc_ade_enable(struct hisi_drm_ade_crtc *crtc_ade)
}
}

ade_set_medianoc_qos(crtc_ade);
ade_init(crtc_ade);
ldi_init(crtc_ade);
if (crtc_ade->crtc.primary->fb)
Expand Down Expand Up @@ -448,9 +477,17 @@ static int hisi_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
ade_base + ADE_CTRAN6_IMAGE_SIZE_REG);

/* enable ade and ldi */
crtc_ade->res_switch_cmpl = 0;
writel(ADE_ENABLE, ade_base + ADE_EN_REG);
set_TOP_CTL_frm_end_start(ade_base, 1);
set_LDI_CTRL_ldi_en(ade_base, ADE_ENABLE);
if (wait_event_interruptible_timeout(crtc_ade->wait_res_cmpl, crtc_ade->res_switch_cmpl, HZ/4) <= 0) {
DRM_INFO("wait_event_interruptible_timeout wait_res_cmpl timeout!\n");
writel(0, ade_base + ADE_SOFT_RST_SEL0_REG);
writel(0, ade_base + ADE_SOFT_RST_SEL1_REG);
writel(0xffffffff, ade_base + ADE_SOFT_RST0_REG);
writel(0xffffffff, ade_base + ADE_SOFT_RST1_REG);
}
crtc_ade->res_switch_cmpl = 0;

DRM_DEBUG_DRIVER("mode_set_base exit successfully.\n");
return 0;
Expand Down Expand Up @@ -536,6 +573,13 @@ static int hisi_drm_ade_dts_parse(struct platform_device *pdev,
ret = PTR_ERR(crtc_ade->media_base);
}

res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "media_noc_base");
crtc_ade->media_noc_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(crtc_ade->media_noc_base)) {
DRM_ERROR("failed to remap io region1\n");
ret = PTR_ERR(crtc_ade->media_noc_base);
}

crtc_ade->ade_core_clk = devm_clk_get(&pdev->dev, "clk_ade_core");
if (crtc_ade->ade_core_clk == NULL) {
DRM_ERROR("failed to parse the ADE_CORE\n");
Expand Down Expand Up @@ -569,9 +613,56 @@ static int hisi_drm_ade_dts_parse(struct platform_device *pdev,
return ret;
}

static irqreturn_t ade_irq_handler(int irq, void *data)
{
struct hisi_drm_ade_crtc *acrtc = data;
void __iomem *base = acrtc->ade_base;
u32 status0, status1;

status0 = readl(base + INTR_MASK_STATE_CPU_0_REG);
status1 = readl(base + INTR_MASK_STATE_CPU_1_REG);

/* check DMA error */
if ((status0 & ADE_ISR_DMA_ERROR) == ADE_ISR_DMA_ERROR) {
writel(ADE_ISR_DMA_ERROR, base + INTR_CLEAR_CPU_0_REG);
DRM_INFO("DMA error check irq\n");
}

if ((status1 & ADE_ISR1_RES_SWITCH_CMPL) == ADE_ISR1_RES_SWITCH_CMPL) {
writel(ADE_ISR1_RES_SWITCH_CMPL, base + INTR_CLEAR_CPU_1_REG);
acrtc->res_switch_cmpl = 1;
wake_up_interruptible_all(&acrtc->wait_res_cmpl);
}

return IRQ_HANDLED;
}

static irqreturn_t ldi_irq_handler(int irq, void *data)
{
struct hisi_drm_ade_crtc *acrtc = data;
void __iomem *base = acrtc->ade_base;
u32 status;

status = readl(base + LDI_MSK_INT_REG);

/* TODO: vblank irq */
if (status & LDI_ISR_FRAME_END_INT) {
writel(LDI_ISR_FRAME_END_INT, base + LDI_INT_CLR_REG);
}

if (status & LDI_ISR_UNDER_FLOW_INT) {
writel(LDI_ISR_UNDER_FLOW_INT, base + LDI_INT_CLR_REG);
DRM_INFO("underflow irq\n");
}

return IRQ_HANDLED;
}

static int hisi_ade_probe(struct platform_device *pdev)
{
struct hisi_drm_ade_crtc *crtc_ade;
int ade_irq;
int ldi_irq;
int ret;

/* debug setting */
Expand All @@ -595,12 +686,38 @@ static int hisi_ade_probe(struct platform_device *pdev)
return ret;
}

ade_irq = platform_get_irq(pdev, 0);
if (ade_irq < 0) {
DRM_ERROR("failed to get ade irq\n");
return ade_irq;
}

ldi_irq = platform_get_irq(pdev, 1);
if (ldi_irq < 0) {
DRM_ERROR("failed to get ldi irq\n");
return ldi_irq;
}

ret = hisi_drm_crtc_create(crtc_ade);
if (ret) {
DRM_ERROR("failed to crtc creat\n");
return ret;
}

/* ade irq init */
ret = devm_request_irq(&pdev->dev, ade_irq, ade_irq_handler, DRIVER_IRQ_SHARED,
"ade irq", crtc_ade);
if (ret)
return ret;

/* ldi irq init */
ret = devm_request_irq(&pdev->dev, ldi_irq, ldi_irq_handler, DRIVER_IRQ_SHARED,
"ldi irq", crtc_ade);
if (ret)
return ret;

init_waitqueue_head(&crtc_ade->wait_res_cmpl);

DRM_DEBUG_DRIVER("drm_ade exit successfully.\n");

return 0;
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/i2c/adv7511.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ static void adv7511_set_link_config(struct adv7511 *adv7511,

static void adv7511_dsi_config_tgen(struct adv7511 *adv7511)
{
struct drm_display_mode *mode = adv7511->curr_mode;
struct drm_display_mode *mode = &adv7511->curr_mode;
unsigned int hsw, hfp, hbp, vsw, vfp, vbp, hd, vd;

hsw = mode->hsync_end - mode->hsync_start;
Expand Down Expand Up @@ -856,7 +856,7 @@ static void adv7511_mode_set(struct adv7511 *adv7511,
regmap_update_bits(adv7511->regmap, 0x17,
0x60, (vsync_polarity << 6) | (hsync_polarity << 5));

adv7511->curr_mode = adj_mode;
memcpy(&adv7511->curr_mode, adj_mode, sizeof(adv7511->curr_mode));
/*
* TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
* supposed to give better results.
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i2c/adv7511.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ struct adv7511 {
enum drm_connector_status status;
bool powered;

struct drm_display_mode *curr_mode;
struct drm_display_mode curr_mode;

unsigned int f_tmds;
unsigned int f_audio;
Expand Down

0 comments on commit c3e766c

Please sign in to comment.