[PATCH v3 3/3] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR

2016-09-20 Thread Yakir Yang
Hi Sean,

On 09/12/2016 09:52 PM, Sean Paul wrote:
> On Fri, Sep 9, 2016 at 5:45 AM, Yakir Yang  wrote:
>> Make sure the request PSR state takes effect in analogix_dp_send_psr_spd()
>> function, or print the sink PSR error state if we failed to apply the
>> requested PSR setting.
>>
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v3:
>> - Update commit message
>> - Add DP_TIMEOUT_PSR_LOOP_MS marcos
>> - Correct the return values of analogix_dp_send_psr_spd()
>>
>> Changes in v2:
>> - A bunch of good fixes from Sean
>>
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  6 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 +++--
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 25 
>> --
>>   3 files changed, 28 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 5fe3982..c0ce16a 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -116,8 +116,7 @@ int analogix_dp_enable_psr(struct device *dev)
>>  psr_vsc.DB0 = 0;
>>  psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | 
>> EDP_VSC_PSR_CRC_VALUES_VALID;
>>
>> -   analogix_dp_send_psr_spd(dp, _vsc);
>> -   return 0;
>> +   return analogix_dp_send_psr_spd(dp, _vsc);
>>   }
>>   EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
>>
>> @@ -139,8 +138,7 @@ int analogix_dp_disable_psr(struct device *dev)
>>  psr_vsc.DB0 = 0;
>>  psr_vsc.DB1 = 0;
>>
>> -   analogix_dp_send_psr_spd(dp, _vsc);
>> -   return 0;
>> +   return analogix_dp_send_psr_spd(dp, _vsc);
>>   }
>>   EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> index d564e90..a27f1e3 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> @@ -20,6 +20,7 @@
>>   #define MAX_EQ_LOOP 5
>>
>>   #define DP_TIMEOUT_LOOP_MS msecs_to_jiffies(1)
>> +#define DP_TIMEOUT_PSR_LOOP_MS msecs_to_jiffies(300)
> Same comment here re: units.
>
> 300ms seems like a really long time. Why does it take this long?

This magic number '300ms' just come from my test, I haven't found the 
description in eDP 1.4a Spec about what exact time should Sink take to 
entry PSR.

- Yakir

> Sean
>
>
>>   /* DP_MAX_LANE_COUNT */
>>   #define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
>> @@ -248,8 +249,8 @@ void analogix_dp_config_video_slave_mode(struct 
>> analogix_dp_device *dp);
>>   void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
>>   void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
>>   void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
>> -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> - struct edp_vsc_psr *vsc);
>> +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> +struct edp_vsc_psr *vsc);
>>   ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
>>   struct drm_dp_aux_msg *msg);
>>   #endif /* _ANALOGIX_DP_CORE_H */
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> index 15a4cf0..7fd4ed0 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> @@ -1004,10 +1004,12 @@ void analogix_dp_enable_psr_crc(struct 
>> analogix_dp_device *dp)
>>  writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);
>>   }
>>
>> -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> - struct edp_vsc_psr *vsc)
>> +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> +struct edp_vsc_psr *vsc)
>>   {
>> +   unsigned long timeout;
>>  unsigned int val;
>> +   u8 sink;
>>
>>  /* don't send info frame */
>>  val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
>> @@ -1048,6 +1050,25 @@ void analogix_dp_send_psr_spd(struct 
>> analogix_dp_device *dp,
>>  val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEN

[PATCH v3 2/3] drm/bridge: analogix_dp: use jiffies to simulate timeout loop

2016-09-20 Thread Yakir Yang
Hi Sean,


On 09/12/2016 09:51 PM, Sean Paul wrote:
> On Fri, Sep 9, 2016 at 5:44 AM, Yakir Yang  wrote:
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v3:
>> - Suggested by Sean
>>
>> Changes in v2: None
>>
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  3 ++-
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 18 +-
>>   2 files changed, 11 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> index a15f076..d564e90 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> @@ -16,10 +16,11 @@
>>   #include 
>>   #include 
>>
>> -#define DP_TIMEOUT_LOOP_COUNT 100
>>   #define MAX_CR_LOOP 5
>>   #define MAX_EQ_LOOP 5
>>
>> +#define DP_TIMEOUT_LOOP_MS msecs_to_jiffies(1)
> The name suggests the units here are ms, but you're storing jiffies.
> Do the msecs_to_jiffies conversion down below.

I suddenly realized that 'analogix_dp_core.c' also used the 
'DP_TIMEOUT_LOOP_COUNT' macros, and 'analogix_dp_core.c' have four kinds 
of timeout,
   - DP_TIMEOUT_LOOP_COUNT * 1us
   - DP_TIMEOUT_LOOP_COUNT * 10us
   - DP_TIMEOUT_LOOP_COUNT * 100us
   - DP_TIMEOUT_LOOP_COUNT * 1000us

I may guess it's not necessary to replace the 'DP_TIMEOUT_LOOP_COUNT' 
now  :-)

- Yakir

>
>> +
>>   /* DP_MAX_LANE_COUNT */
>>   #define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
>>   #define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> index a4d17b8..15a4cf0 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> @@ -335,7 +335,7 @@ void analogix_dp_set_analog_power_down(struct 
>> analogix_dp_device *dp,
>>   void analogix_dp_init_analog_func(struct analogix_dp_device *dp)
>>   {
>>  u32 reg;
>> -   int timeout_loop = 0;
>> +   unsigned long timeout;
>>
>>  analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);
>>
>> @@ -350,9 +350,9 @@ void analogix_dp_init_analog_func(struct 
>> analogix_dp_device *dp)
>>  if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
>>  analogix_dp_set_pll_power_down(dp, 0);
>>
>> +   timeout = jiffies + DP_TIMEOUT_LOOP_MS;
> timeout = jiffies + msecs_to_jiffies(DP_TIMEOUT_LOOP_MS);
>
>>  while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) 
>> {
>> -   timeout_loop++;
>> -   if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> +   if (time_after(jiffies, timeout)) {
>>  dev_err(dp->dev, "failed to get pll lock 
>> status\n");
>>  return;
>>  }
>> @@ -501,7 +501,7 @@ int analogix_dp_start_aux_transaction(struct 
>> analogix_dp_device *dp)
>>   {
>>  int reg;
>>  int retval = 0;
>> -   int timeout_loop = 0;
>> +   unsigned long timeout;
>>
>>  /* Enable AUX CH operation */
>>  reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
>> @@ -509,10 +509,10 @@ int analogix_dp_start_aux_transaction(struct 
>> analogix_dp_device *dp)
>>  writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
>>
>>  /* Is AUX CH command reply received? */
>> +   timeout = jiffies + DP_TIMEOUT_LOOP_MS;
>>  reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
>>  while (!(reg & RPLY_RECEIV)) {
>> -   timeout_loop++;
>> -   if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
>> +   if (time_after(jiffies, timeout)) {
>>  dev_err(dp->dev, "AUX CH command reply failed!\n");
>>  return -ETIMEDOUT;
>>  }
>> @@ -1055,7 +1055,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device 
>> *dp,
>>   {
>>  u32 reg;
>>  u8 *buffer = msg->buffer;
>> -   int timeout_loop = 0;
>> +   unsigned long timeout;
>>  unsigned int i;
>>  int num_transferred = 0;
>>
>> @@ -1123,10 +1123,10 @@ ssize_t analogix_dp_transfer(struct 
>> analogix_dp_device *dp,
>>
>>  /* Is AUX CH command reply received? */
>>  /* TODO: Wait for an interrupt instead of looping? */
>> +   timeout = jiffies + DP_TIMEOUT_LOOP_MS;
>>  reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
>>  while (!(reg & RPLY_RECEIV)) {
>> -   timeout_loop++;
>> -   if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) {
>> +   if (time_after(jiffies, timeout)) {
>>  dev_err(dp->dev, "AUX CH command reply failed!\n");
>>  return -ETIMEDOUT;
>>  }
>> --
>> 1.9.1
>>
>>
>
>




[PATCH v3 3/3] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR

2016-09-09 Thread Yakir Yang
Make sure the request PSR state takes effect in analogix_dp_send_psr_spd()
function, or print the sink PSR error state if we failed to apply the
requested PSR setting.

Signed-off-by: Yakir Yang 
---
Changes in v3:
- Update commit message
- Add DP_TIMEOUT_PSR_LOOP_MS marcos
- Correct the return values of analogix_dp_send_psr_spd()

Changes in v2:
- A bunch of good fixes from Sean

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  6 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 +++--
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 25 --
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5fe3982..c0ce16a 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -116,8 +116,7 @@ int analogix_dp_enable_psr(struct device *dev)
psr_vsc.DB0 = 0;
psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;

-   analogix_dp_send_psr_spd(dp, _vsc);
-   return 0;
+   return analogix_dp_send_psr_spd(dp, _vsc);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);

@@ -139,8 +138,7 @@ int analogix_dp_disable_psr(struct device *dev)
psr_vsc.DB0 = 0;
psr_vsc.DB1 = 0;

-   analogix_dp_send_psr_spd(dp, _vsc);
-   return 0;
+   return analogix_dp_send_psr_spd(dp, _vsc);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index d564e90..a27f1e3 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -20,6 +20,7 @@
 #define MAX_EQ_LOOP 5

 #define DP_TIMEOUT_LOOP_MS msecs_to_jiffies(1)
+#define DP_TIMEOUT_PSR_LOOP_MS msecs_to_jiffies(300)

 /* DP_MAX_LANE_COUNT */
 #define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
@@ -248,8 +249,8 @@ void analogix_dp_config_video_slave_mode(struct 
analogix_dp_device *dp);
 void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
-void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
- struct edp_vsc_psr *vsc);
+int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
+struct edp_vsc_psr *vsc);
 ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
 struct drm_dp_aux_msg *msg);
 #endif /* _ANALOGIX_DP_CORE_H */
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 15a4cf0..7fd4ed0 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -1004,10 +1004,12 @@ void analogix_dp_enable_psr_crc(struct 
analogix_dp_device *dp)
writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);
 }

-void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
- struct edp_vsc_psr *vsc)
+int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
+struct edp_vsc_psr *vsc)
 {
+   unsigned long timeout;
unsigned int val;
+   u8 sink;

/* don't send info frame */
val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
@@ -1048,6 +1050,25 @@ void analogix_dp_send_psr_spd(struct analogix_dp_device 
*dp,
val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
val |= IF_EN;
writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
+
+   timeout = jiffies + DP_TIMEOUT_PSR_LOOP_MS;
+   while (time_before(jiffies, timeout)) {
+   val = drm_dp_dpcd_readb(>aux, DP_PSR_STATUS, );
+   if (val != 1) {
+   dev_err(dp->dev, "PSR_STATUS read failed ret=%d", val);
+   return -EBUSY;
+   }
+
+   if ((vsc->DB1 && sink == DP_PSR_SINK_ACTIVE_RFB) ||
+   (!vsc->DB1 && sink == DP_PSR_SINK_INACTIVE))
+   return 0;
+
+   usleep_range(1000, 1500);
+   }
+
+   dev_warn(dp->dev, "Failed to apply PSR, sink state was [%x]", sink);
+
+   return -ETIMEDOUT;
 }

 ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
-- 
1.9.1




[PATCH v3 2/3] drm/bridge: analogix_dp: use jiffies to simulate timeout loop

2016-09-09 Thread Yakir Yang
Signed-off-by: Yakir Yang 
---
Changes in v3:
- Suggested by Sean

Changes in v2: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  3 ++-
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 18 +-
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index a15f076..d564e90 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -16,10 +16,11 @@
 #include 
 #include 

-#define DP_TIMEOUT_LOOP_COUNT 100
 #define MAX_CR_LOOP 5
 #define MAX_EQ_LOOP 5

+#define DP_TIMEOUT_LOOP_MS msecs_to_jiffies(1)
+
 /* DP_MAX_LANE_COUNT */
 #define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
 #define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index a4d17b8..15a4cf0 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -335,7 +335,7 @@ void analogix_dp_set_analog_power_down(struct 
analogix_dp_device *dp,
 void analogix_dp_init_analog_func(struct analogix_dp_device *dp)
 {
u32 reg;
-   int timeout_loop = 0;
+   unsigned long timeout;

analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);

@@ -350,9 +350,9 @@ void analogix_dp_init_analog_func(struct analogix_dp_device 
*dp)
if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
analogix_dp_set_pll_power_down(dp, 0);

+   timeout = jiffies + DP_TIMEOUT_LOOP_MS;
while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-   timeout_loop++;
-   if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+   if (time_after(jiffies, timeout)) {
dev_err(dp->dev, "failed to get pll lock 
status\n");
return;
}
@@ -501,7 +501,7 @@ int analogix_dp_start_aux_transaction(struct 
analogix_dp_device *dp)
 {
int reg;
int retval = 0;
-   int timeout_loop = 0;
+   unsigned long timeout;

/* Enable AUX CH operation */
reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
@@ -509,10 +509,10 @@ int analogix_dp_start_aux_transaction(struct 
analogix_dp_device *dp)
writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);

/* Is AUX CH command reply received? */
+   timeout = jiffies + DP_TIMEOUT_LOOP_MS;
reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
while (!(reg & RPLY_RECEIV)) {
-   timeout_loop++;
-   if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+   if (time_after(jiffies, timeout)) {
dev_err(dp->dev, "AUX CH command reply failed!\n");
return -ETIMEDOUT;
}
@@ -1055,7 +1055,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device 
*dp,
 {
u32 reg;
u8 *buffer = msg->buffer;
-   int timeout_loop = 0;
+   unsigned long timeout;
unsigned int i;
int num_transferred = 0;

@@ -1123,10 +1123,10 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device 
*dp,

/* Is AUX CH command reply received? */
/* TODO: Wait for an interrupt instead of looping? */
+   timeout = jiffies + DP_TIMEOUT_LOOP_MS;
reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
while (!(reg & RPLY_RECEIV)) {
-   timeout_loop++;
-   if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) {
+   if (time_after(jiffies, timeout)) {
dev_err(dp->dev, "AUX CH command reply failed!\n");
return -ETIMEDOUT;
}
-- 
1.9.1




[PATCH v2 2/2] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR

2016-09-09 Thread Yakir Yang
On 09/08/2016 10:12 PM, Sean Paul wrote:
> On Wed, Sep 7, 2016 at 11:48 PM, Yakir Yang  wrote:
>> Make sure the request PSR state could effect in analogix_dp_send_psr_spd()
>> function, or printing the error Sink PSR state if we failed to effect
>> the request PSR setting.
>>
>
> Let's change to:
>
> Make sure the request PSR state takes effect in analogix_dp_send_psr_spd()
> function, or print the sink PSR error state if we failed to apply the
> requested PSR
> setting.
Done,
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v2:
>> - A bunch of good fixes from Sean
>>
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  6 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++--
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 25 
>> --
>>   3 files changed, 27 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 5fe3982..c0ce16a 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -116,8 +116,7 @@ int analogix_dp_enable_psr(struct device *dev)
>>  psr_vsc.DB0 = 0;
>>  psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | 
>> EDP_VSC_PSR_CRC_VALUES_VALID;
>>
>> -   analogix_dp_send_psr_spd(dp, _vsc);
>> -   return 0;
>> +   return analogix_dp_send_psr_spd(dp, _vsc);
>>   }
>>   EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
>>
>> @@ -139,8 +138,7 @@ int analogix_dp_disable_psr(struct device *dev)
>>  psr_vsc.DB0 = 0;
>>  psr_vsc.DB1 = 0;
>>
>> -   analogix_dp_send_psr_spd(dp, _vsc);
>> -   return 0;
>> +   return analogix_dp_send_psr_spd(dp, _vsc);
>>   }
>>   EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> index a15f076..6c07a50 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> @@ -247,8 +247,8 @@ void analogix_dp_config_video_slave_mode(struct 
>> analogix_dp_device *dp);
>>   void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
>>   void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
>>   void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
>> -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> - struct edp_vsc_psr *vsc);
>> +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> +struct edp_vsc_psr *vsc);
>>   ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
>>   struct drm_dp_aux_msg *msg);
>>   #endif /* _ANALOGIX_DP_CORE_H */
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> index a4d17b8..09d703b 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> @@ -1004,10 +1004,12 @@ void analogix_dp_enable_psr_crc(struct 
>> analogix_dp_device *dp)
>>  writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);
>>   }
>>
>> -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> - struct edp_vsc_psr *vsc)
>> +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> +struct edp_vsc_psr *vsc)
>>   {
>> +   unsigned long timeout;
>>  unsigned int val;
>> +   u8 sink;
>>
>>  /* don't send info frame */
>>  val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
>> @@ -1048,6 +1050,25 @@ void analogix_dp_send_psr_spd(struct 
>> analogix_dp_device *dp,
>>  val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
>>  val |= IF_EN;
>>  writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
>> +
>> +   timeout = jiffies + msecs_to_jiffies(DP_TIMEOUT_LOOP_COUNT);
> Mismatched units here. DP_TIMEOUT_LOOP_COUNT is defined as number of
> retries, whereas you're using it as number of ms. Fortunately, the
> retry number is so high that this works out :)
>
> In a separate patch preceding this one, can you change
> DP_TIMEOUT_LOOP_COUNT to DP_TIMEOUT_LOOP_MS and alter the other
> timeout loops to use time_before() like this one instead of blin

[PATCH v2 2/2] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR

2016-09-08 Thread Yakir Yang
Make sure the request PSR state could effect in analogix_dp_send_psr_spd()
function, or printing the error Sink PSR state if we failed to effect
the request PSR setting.

Signed-off-by: Yakir Yang 
---
Changes in v2:
- A bunch of good fixes from Sean

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  6 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++--
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 25 --
 3 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5fe3982..c0ce16a 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -116,8 +116,7 @@ int analogix_dp_enable_psr(struct device *dev)
psr_vsc.DB0 = 0;
psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;

-   analogix_dp_send_psr_spd(dp, _vsc);
-   return 0;
+   return analogix_dp_send_psr_spd(dp, _vsc);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);

@@ -139,8 +138,7 @@ int analogix_dp_disable_psr(struct device *dev)
psr_vsc.DB0 = 0;
psr_vsc.DB1 = 0;

-   analogix_dp_send_psr_spd(dp, _vsc);
-   return 0;
+   return analogix_dp_send_psr_spd(dp, _vsc);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index a15f076..6c07a50 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -247,8 +247,8 @@ void analogix_dp_config_video_slave_mode(struct 
analogix_dp_device *dp);
 void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
-void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
- struct edp_vsc_psr *vsc);
+int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
+struct edp_vsc_psr *vsc);
 ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
 struct drm_dp_aux_msg *msg);
 #endif /* _ANALOGIX_DP_CORE_H */
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index a4d17b8..09d703b 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -1004,10 +1004,12 @@ void analogix_dp_enable_psr_crc(struct 
analogix_dp_device *dp)
writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);
 }

-void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
- struct edp_vsc_psr *vsc)
+int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
+struct edp_vsc_psr *vsc)
 {
+   unsigned long timeout;
unsigned int val;
+   u8 sink;

/* don't send info frame */
val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
@@ -1048,6 +1050,25 @@ void analogix_dp_send_psr_spd(struct analogix_dp_device 
*dp,
val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
val |= IF_EN;
writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
+
+   timeout = jiffies + msecs_to_jiffies(DP_TIMEOUT_LOOP_COUNT);
+   while (time_before(jiffies, timeout)) {
+   val = drm_dp_dpcd_readb(>aux, DP_PSR_STATUS, );
+   if (val != 1) {
+   dev_err(dp->dev, "PSR_STATUS read failed ret=%d", val);
+   return val;
+   }
+
+   if (vsc->DB1 && sink == DP_PSR_SINK_ACTIVE_RFB ||
+   !vsc->DB1 && sink == DP_PSR_SINK_INACTIVE)
+   break;
+
+   usleep_range(1000, 1500);
+   }
+
+   dev_warn(dp->dev, "Failed to effect PSR: %x", sink);
+
+   return -ETIMEDOUT;
 }

 ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
-- 
1.9.1




[PATCH v2 1/2] drm/bridge: analogix_dp: Remove duplicated code v2

2016-09-08 Thread Yakir Yang
From: Tomeu Vizoso <tomeu.viz...@collabora.com>

Remove code for reading the EDID and DPCD fields and use the helpers
instead.

Besides the obvious code reduction, other helpers are being added to the
core that could be used in this driver and will be good to be able to
use them instead of duplicating them.

Signed-off-by: Tomeu Vizoso 
Cc: Javier Martinez Canillas 
Cc: Mika Kahola 
Cc: Yakir Yang 
Cc: Daniel Vetter 

Reviewed-by: Sean Paul 
Reviewed-by: Yakir Yang 
Tested-by: Javier Martinez Canillas 
Tested-by: Sean Paul 
---
Changes in v2:
- A bunch of good fixes from Sean and Yakir
- Moved the transfer function to analogix_dp_reg.c
- Removed reference to the EDID from the dp struct
- Rebase on Sean's next tree
git://people.freedesktop.org/~seanpaul/dogwood

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 263 
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  41 +-
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 451 ++---
 3 files changed, 204 insertions(+), 551 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index efac8ab..5fe3982 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -31,6 +31,7 @@
 #include 

 #include "analogix_dp_core.h"
+#include "analogix_dp_reg.h"

 #define to_dp(nm)  container_of(nm, struct analogix_dp_device, nm)

@@ -174,150 +175,21 @@ static void analogix_dp_enable_sink_psr(struct 
analogix_dp_device *dp)
analogix_dp_enable_psr_crc(dp);
 }

-static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
-{
-   int i;
-   unsigned char sum = 0;
-
-   for (i = 0; i < EDID_BLOCK_LENGTH; i++)
-   sum = sum + edid_data[i];
-
-   return sum;
-}
-
-static int analogix_dp_read_edid(struct analogix_dp_device *dp)
-{
-   unsigned char *edid = dp->edid;
-   unsigned int extend_block = 0;
-   unsigned char sum;
-   unsigned char test_vector;
-   int retval;
-
-   /*
-* EDID device address is 0x50.
-* However, if necessary, you must have set upper address
-* into E-EDID in I2C device, 0x30.
-*/
-
-   /* Read Extension Flag, Number of 128-byte EDID extension blocks */
-   retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-   EDID_EXTENSION_FLAG,
-   _block);
-   if (retval)
-   return retval;
-
-   if (extend_block > 0) {
-   dev_dbg(dp->dev, "EDID data includes a single extension!\n");
-
-   /* Read EDID data */
-   retval = analogix_dp_read_bytes_from_i2c(dp,
-   I2C_EDID_DEVICE_ADDR,
-   EDID_HEADER_PATTERN,
-   EDID_BLOCK_LENGTH,
-   [EDID_HEADER_PATTERN]);
-   if (retval != 0) {
-   dev_err(dp->dev, "EDID Read failed!\n");
-   return -EIO;
-   }
-   sum = analogix_dp_calc_edid_check_sum(edid);
-   if (sum != 0) {
-   dev_err(dp->dev, "EDID bad checksum!\n");
-   return -EIO;
-   }
-
-   /* Read additional EDID data */
-   retval = analogix_dp_read_bytes_from_i2c(dp,
-   I2C_EDID_DEVICE_ADDR,
-   EDID_BLOCK_LENGTH,
-   EDID_BLOCK_LENGTH,
-   [EDID_BLOCK_LENGTH]);
-   if (retval != 0) {
-   dev_err(dp->dev, "EDID Read failed!\n");
-   return -EIO;
-   }
-   sum = analogix_dp_calc_edid_check_sum([EDID_BLOCK_LENGTH]);
-   if (sum != 0) {
-   dev_err(dp->dev, "EDID bad checksum!\n");
-   return -EIO;
-   }
-
-   analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
-   _vector);
-   if (test_vector & DP_TEST_LINK_EDID_READ) {
-   analogix_dp_write_byte_to_dpcd(dp,
-   DP_TEST_EDID_CHECKSUM,
-   edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
-   analogix_dp_write_byte_to_dpcd(dp,
-   DP_TEST_RESPONSE,
-   DP_TEST_EDID_CHECKSUM_WRITE);
-   }
-   } else {
-   dev_info(dp->dev, "EDID data does not include any 
extensions.\n");
-
-   /* Read EDID data */
-   r

[PATCH] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR

2016-09-07 Thread Yakir Yang
Sean,

Thanks for your comments.

On 09/07/2016 03:51 AM, Sean Paul wrote:
> On Fri, Aug 26, 2016 at 6:19 AM, Yakir Yang  wrote:
>> Make sure the request PSR state could effect in analogix_dp_send_psr_spd()
>> function, or printing the error Sink PSR state if we failed to effect
>> the request PSR setting.
>>
>> Signed-off-by: Yakir Yang 
>> ---
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  6 ++---
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++--
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 26 
>> --
>>   3 files changed, 28 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index efac8ab..5a37de8 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -115,8 +115,7 @@ int analogix_dp_enable_psr(struct device *dev)
>>  psr_vsc.DB0 = 0;
>>  psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | 
>> EDP_VSC_PSR_CRC_VALUES_VALID;
>>
>> -   analogix_dp_send_psr_spd(dp, _vsc);
>> -   return 0;
>> +   return analogix_dp_send_psr_spd(dp, _vsc);
>>   }
>>   EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
>>
>> @@ -138,8 +137,7 @@ int analogix_dp_disable_psr(struct device *dev)
>>  psr_vsc.DB0 = 0;
>>  psr_vsc.DB1 = 0;
>>
>> -   analogix_dp_send_psr_spd(dp, _vsc);
>> -   return 0;
>> +   return analogix_dp_send_psr_spd(dp, _vsc);
>>   }
>>   EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> index 473b980..f617a9d 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>> @@ -283,7 +283,7 @@ void analogix_dp_config_video_slave_mode(struct 
>> analogix_dp_device *dp);
>>   void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
>>   void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
>>   void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
>> -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> - struct edp_vsc_psr *vsc);
>> +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> +struct edp_vsc_psr *vsc);
>>
>>   #endif /* _ANALOGIX_DP_CORE_H */
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> index 52c1b6b..505e9d8 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>> @@ -1328,9 +1328,11 @@ void analogix_dp_enable_psr_crc(struct 
>> analogix_dp_device *dp)
>>  writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);
>>   }
>>
>> -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> - struct edp_vsc_psr *vsc)
>> +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
>> +struct edp_vsc_psr *vsc)
>>   {
>> +   unsigned long timeout;
>> +   unsigned char sink;
> u8
Done
>>  unsigned int val;
>>
>>  /* don't send info frame */
>> @@ -1372,4 +1374,24 @@ void analogix_dp_send_psr_spd(struct 
>> analogix_dp_device *dp,
>>  val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
>>  val |= IF_EN;
>>  writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
>> +
>> +   timeout = jiffies + msecs_to_jiffies(100);
> Pull 100 out into a #define
Done
>> +   while (1) {
>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_STATUS, );
> You should be checking return value here.
Done
>> +
>> +   if (vsc->DB1 && sink == DP_PSR_SINK_ACTIVE_RFB)
>> +   break;
>> +
>> +   if (!vsc->DB1 && sink == DP_PSR_SINK_INACTIVE)
>> +   break;
>> +
>> +   if (time_after(jiffies, timeout)) {
>> +   dev_warn(dp->dev, "Failed to effect PSR: %x", sink);
>> +   return -EBUSY;
> -ETIMEDOUT is more appropriate
Done
>> +   }
>> +
>> +   usleep_range(1000, 1500);
>> +   }
> The while(1) loop is a little 

[PATCH] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR

2016-08-26 Thread Yakir Yang
Make sure the request PSR state could effect in analogix_dp_send_psr_spd()
function, or printing the error Sink PSR state if we failed to effect
the request PSR setting.

Signed-off-by: Yakir Yang 
---
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  6 ++---
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++--
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 26 --
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index efac8ab..5a37de8 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -115,8 +115,7 @@ int analogix_dp_enable_psr(struct device *dev)
psr_vsc.DB0 = 0;
psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;

-   analogix_dp_send_psr_spd(dp, _vsc);
-   return 0;
+   return analogix_dp_send_psr_spd(dp, _vsc);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);

@@ -138,8 +137,7 @@ int analogix_dp_disable_psr(struct device *dev)
psr_vsc.DB0 = 0;
psr_vsc.DB1 = 0;

-   analogix_dp_send_psr_spd(dp, _vsc);
-   return 0;
+   return analogix_dp_send_psr_spd(dp, _vsc);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index 473b980..f617a9d 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -283,7 +283,7 @@ void analogix_dp_config_video_slave_mode(struct 
analogix_dp_device *dp);
 void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
-void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
- struct edp_vsc_psr *vsc);
+int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
+struct edp_vsc_psr *vsc);

 #endif /* _ANALOGIX_DP_CORE_H */
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 52c1b6b..505e9d8 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -1328,9 +1328,11 @@ void analogix_dp_enable_psr_crc(struct 
analogix_dp_device *dp)
writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);
 }

-void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
- struct edp_vsc_psr *vsc)
+int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
+struct edp_vsc_psr *vsc)
 {
+   unsigned long timeout;
+   unsigned char sink;
unsigned int val;

/* don't send info frame */
@@ -1372,4 +1374,24 @@ void analogix_dp_send_psr_spd(struct analogix_dp_device 
*dp,
val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
val |= IF_EN;
writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
+
+   timeout = jiffies + msecs_to_jiffies(100);
+   while (1) {
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_STATUS, );
+
+   if (vsc->DB1 && sink == DP_PSR_SINK_ACTIVE_RFB)
+   break;
+
+   if (!vsc->DB1 && sink == DP_PSR_SINK_INACTIVE)
+   break;
+
+   if (time_after(jiffies, timeout)) {
+   dev_warn(dp->dev, "Failed to effect PSR: %x", sink);
+   return -EBUSY;
+   }
+
+   usleep_range(1000, 1500);
+   }
+
+   return 0;
 }
-- 
1.9.1




[PATCH 2/3] drm/rockchip: Don't key off vblank for psr

2016-08-26 Thread Yakir Yang
Sean,

Thanks for this good fix.

On 08/19/2016 07:34 AM, Sean Paul wrote:
> Instead of keying off vblank for psr, just flush every time
> we get an atomic update. This ensures that cursor updates
> will properly disable psr (without turning vblank on/off),
> and unifies the paths between fb_dirty and atomic psr
> enable/disable.
>
> Signed-off-by: Sean Paul 

Reviewed-by: Yakir Yang 

Also I have verified this patch on RK3399 Kevin, eDP PSR works rightly, so

Tested-by: Yakir Yang 

- Yakir

> ---
>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  2 +-
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 72 
> -
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  8 ++--
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 10 ++--
>   4 files changed, 62 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> index ba45d9d..10cafbc 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> @@ -70,7 +70,7 @@ static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
>struct drm_clip_rect *clips,
>unsigned int num_clips)
>   {
> - rockchip_drm_psr_flush(fb->dev);
> + rockchip_drm_psr_flush_all(fb->dev);
>   return 0;
>   }
>   
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> index c6ac5d0..de6252f 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> @@ -31,6 +31,7 @@ struct psr_drv {
>   struct drm_encoder  *encoder;
>   
>   spinlock_t  lock;
> + boolactive;
>   enum psr_state  state;
>   
>   struct timer_list   flush_timer;
> @@ -67,11 +68,7 @@ static void psr_set_state_locked(struct psr_drv *psr, enum 
> psr_state state)
>*   v ||
>*   PSR_DISABLE < - - - - - - - - -
>*/
> - if (state == psr->state)
> - return;
> -
> - /* Requesting a flush when disabled is a noop */
> - if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
> + if (state == psr->state || !psr->active)
>   return;
>   
>   psr->state = state;
> @@ -115,45 +112,79 @@ static void psr_flush_handler(unsigned long data)
>   }
>   
>   /**
> - * rockchip_drm_psr_enable - enable the encoder PSR which bind to given CRTC
> + * rockchip_drm_psr_activate - activate PSR on the given pipe
>* @crtc: CRTC to obtain the PSR encoder
>*
>* Returns:
>* Zero on success, negative errno on failure.
>*/
> -int rockchip_drm_psr_enable(struct drm_crtc *crtc)
> +int rockchip_drm_psr_activate(struct drm_crtc *crtc)
>   {
>   struct psr_drv *psr = find_psr_by_crtc(crtc);
> + unsigned long flags;
>   
>   if (IS_ERR(psr))
>   return PTR_ERR(psr);
>   
> - psr_set_state(psr, PSR_ENABLE);
> + spin_lock_irqsave(>lock, flags);
> + psr->active = true;
> + spin_unlock_irqrestore(>lock, flags);
> +
>   return 0;
>   }
> -EXPORT_SYMBOL(rockchip_drm_psr_enable);
> +EXPORT_SYMBOL(rockchip_drm_psr_activate);
>   
>   /**
> - * rockchip_drm_psr_disable - disable the encoder PSR which bind to given 
> CRTC
> + * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe
>* @crtc: CRTC to obtain the PSR encoder
>*
>* Returns:
>* Zero on success, negative errno on failure.
>*/
> -int rockchip_drm_psr_disable(struct drm_crtc *crtc)
> +int rockchip_drm_psr_deactivate(struct drm_crtc *crtc)
>   {
>   struct psr_drv *psr = find_psr_by_crtc(crtc);
> + unsigned long flags;
> +
> + if (IS_ERR(psr))
> + return PTR_ERR(psr);
> +
> + spin_lock_irqsave(>lock, flags);
> + psr->active = false;
> + spin_unlock_irqrestore(>lock, flags);
> + del_timer_sync(>flush_timer);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
> +
> +static void rockchip_drm_do_flush(struct psr_drv *psr)
> +{
> + mod_timer(>flush_timer,
> +   round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
> + psr_set_state(psr, PSR_FLUSH);
> +}
>   
> +/**
> + * rockchip_drm_psr_flush - flush a single pipe
> + * @crtc: CRTC of the pipe to flush
> + *
> + * Returns:
> + * 0 on success, -errno on fail
> + */
> +int rockchip_drm_psr_flush(struct drm_crtc *crtc)
> +{
> + struct psr_drv *psr = find_psr_by_crtc(crt

[PATCH 3/3] drm/rockchip: Reduce psr flush time to 100ms

2016-08-26 Thread Yakir Yang
Sean,

On 08/19/2016 07:34 AM, Sean Paul wrote:
> 3 seconds is a bit too conservative, drop this to 100ms for
> better power savings.
>
> Signed-off-by: Sean Paul 

Reviewed-by: Yakir Yang 

> ---
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> index de6252f..2cdd6eb 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> @@ -18,7 +18,7 @@
>   #include "rockchip_drm_drv.h"
>   #include "rockchip_drm_psr.h"
>   
> -#define PSR_FLUSH_TIMEOUTmsecs_to_jiffies(3000) /* 3 seconds */
> +#define PSR_FLUSH_TIMEOUTmsecs_to_jiffies(100)
>   
>   enum psr_state {
>   PSR_FLUSH,




[PATCH v3] drm/bridge: analogix_dp: Remove duplicated code

2016-08-25 Thread Yakir Yang
On 08/24/2016 10:54 PM, Sean Paul wrote:
> From: Tomeu Vizoso
>
> Remove code for reading the EDID and DPCD fields and use the helpers
> instead.
>
> Besides the obvious code reduction, other helpers are being added to the
> core that could be used in this driver and will be good to be able to
> use them instead of duplicating them.
>
> Signed-off-by: Tomeu Vizoso
> Tested-by: Javier Martinez Canillas
> Tested-by: Sean Paul
> Reviewed-by: Sean Paul
> Signed-off-by: Sean Paul
> Cc: Javier Martinez Canillas
> Cc: Mika Kahola
> Cc: Yakir Yang
> Cc: Daniel Vetter
> Cc: Archit Taneja

Reviewed-by: Yakir Yang 

> ---
>
> v2:
>  - A bunch of good fixes from Sean and Yakir
>  - Moved the transfer function to analogix_dp_reg.c
>  - Removed reference to the EDID from the dp struct
>
> v3:
>  - Rebased on top of Yakir's PSR series
>  - Fixed checkpatch warning about line length
>
>
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 274 -
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  40 +-
>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 451 
> ++---
>   3 files changed, 210 insertions(+), 555 deletions(-)

-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160825/a6944994/attachment.html>


[PATCH v2] drm/rockchip: Don't continue trying to enable crtc on failure

2016-08-17 Thread Yakir Yang
Sean,

On 08/16/2016 07:12 AM, Sean Paul wrote:
> If vop_enable fails, don't continue on, it causes system hangs.
>
> Signed-off-by: Sean Paul 

Also meet this problem on my Rk3399 Kevin board. VOP just failed to get 
the pm_runtime at resume time, but driver still just continue without 
anything enable rightly, oops, and then system crashed :(

So this patch looks good to me, and also fix my problem, thanks:

Reviewed-by: Yakir Yang 
Tested-by: Yakir Yang 

Thanks,
- Yakir
> ---
>
> This patch uses the new DRM_DEV_ERROR logging, so it should be applied on
> top of "[PATCH 2/2] drm/rockchip: Use DRM_DEV_ERROR in vop".
>
> Changes in v2:
>   - Escalate dev_err to WARN_ON for clk_enable failures (Daniel Vetter)
>
> Sean
>
>
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 31 
> -
>   1 file changed, 17 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index ec8ad00..a176d03 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -428,7 +428,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
> *vop)
>   spin_unlock_irqrestore(>irq_lock, flags);
>   }
>   
> -static void vop_enable(struct drm_crtc *crtc)
> +static int vop_enable(struct drm_crtc *crtc)
>   {
>   struct vop *vop = to_vop(crtc);
>   int ret;
> @@ -436,26 +436,20 @@ static void vop_enable(struct drm_crtc *crtc)
>   ret = pm_runtime_get_sync(vop->dev);
>   if (ret < 0) {
>   dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
> - return;
> + goto err_put_pm_runtime;
>   }
>   
>   ret = clk_enable(vop->hclk);
> - if (ret < 0) {
> - dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
> - return;
> - }
> + if (WARN_ON(ret < 0))
> + goto err_put_pm_runtime;
>   
>   ret = clk_enable(vop->dclk);
> - if (ret < 0) {
> - dev_err(vop->dev, "failed to enable dclk - %d\n", ret);
> + if (WARN_ON(ret < 0))
>   goto err_disable_hclk;
> - }
>   
>   ret = clk_enable(vop->aclk);
> - if (ret < 0) {
> - dev_err(vop->dev, "failed to enable aclk - %d\n", ret);
> + if (WARN_ON(ret < 0))
>   goto err_disable_dclk;
> - }
>   
>   /*
>* Slave iommu shares power, irq and clock with vop.  It was associated
> @@ -485,7 +479,7 @@ static void vop_enable(struct drm_crtc *crtc)
>   
>   drm_crtc_vblank_on(crtc);
>   
> - return;
> + return 0;
>   
>   err_disable_aclk:
>   clk_disable(vop->aclk);
> @@ -493,6 +487,9 @@ err_disable_dclk:
>   clk_disable(vop->dclk);
>   err_disable_hclk:
>   clk_disable(vop->hclk);
> +err_put_pm_runtime:
> + pm_runtime_put_sync(vop->dev);
> + return ret;
>   }
>   
>   static void vop_crtc_disable(struct drm_crtc *crtc)
> @@ -912,10 +909,16 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
>   u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
>   u16 vact_end = vact_st + vdisplay;
>   uint32_t val;
> + int ret;
>   
>   WARN_ON(vop->event);
>   
> - vop_enable(crtc);
> + ret = vop_enable(crtc);
> + if (ret) {
> + DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret);
> + return;
> + }
> +
>   /*
>* If dclk rate is zero, mean that scanout is stop,
>* we don't need wait any more.




[PATCH v5 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-08-17 Thread Yakir Yang
Hello Archit,

On 08/17/2016 01:41 PM, Archit Taneja wrote:
> Hi,
>
> On 07/24/2016 12:27 PM, Yakir Yang wrote:
>> The full name of PSR is Panel Self Refresh, panel device could refresh
>> itself with the hardware framebuffer in panel, this would make lots of
>> sense to save the power consumption.
>>
>> This patch have exported two symbols for platform driver to implement
>> the PSR function in hardware side:
>> - analogix_dp_active_psr()
>> - analogix_dp_inactive_psr()
>
> Could this in any way mess things up if the dev_type is EXYNOS_DP?
>

Nop, I have enabled the panel PSR function by default (if driver detect 
panel support PSR), but this would active the PSR (cause eDP controller 
haven't send the right SDP header), which means panel would stay in 
normal refresh mode on Exynos platform.

I also have tested that case on RK3399 platform. Enable the panel PSR, 
but never call the analogix_dp_active_psr() symbols, and them I found 
panel still refresh normally.

Only when platform driver call the 
analogix_dp_active_psr()/analogix_dp_inactive_psr() symbols in vblank 
time, make the controller to send the active SDP header, then panel 
could enter into PSR mode.

> Otherwise,
>
> Reviewed-by: Archit Taneja 

Thanks for your reviewed.

- Yakir

>
>>
>> Signed-off-by: Yakir Yang 
>> Reviewed-by: Sean Paul 
>> ---
>> Changes in v5:
>> - Add reviewed flag from Sean.
>>
>> Changes in v4.1:
>> - Take use of existing edp_psr_vsc struct to swap HBx and DBx 
>> setting. (Sean)
>> - Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
>> - Add comment about PBx magic numbers. (Sean)
>>
>> Changes in v4:
>> - Downgrade the PSR version print message to debug level. (Sean)
>> - Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). 
>> (Sean)
>> - Delete the unused read dpcd operations in 
>> analogix_dp_enable_sink_psr(). (Sean)
>> - Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. 
>> (Sean).
>> - Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
>> - Rename "active/inactive" to "enable/disable". (Sean, Dominik)
>> - Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().
>>
>> Changes in v3:
>> - split analogix_dp_enable_psr(), make it more clearly
>>  analogix_dp_detect_sink_psr()
>>  analogix_dp_enable_sink_psr()
>> - remove some nosie register setting comments
>>
>> Changes in v2:
>> - introduce in v2, splite the common Analogix DP changes out
>>
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 
>> ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
>>   include/drm/bridge/analogix_dp.h   |  3 +
>>   5 files changed, 174 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 32715da..381b25e 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct 
>> analogix_dp_device *dp)
>>   return 0;
>>   }
>>
>> +int analogix_dp_enable_psr(struct device *dev)
>> +{
>> +struct analogix_dp_device *dp = dev_get_drvdata(dev);
>> +struct edp_vsc_psr psr_vsc;
>> +
>> +if (!dp->psr_support)
>> +return -EINVAL;
>> +
>> +/* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
>> +memset(_vsc, 0, sizeof(psr_vsc));
>> +psr_vsc.sdp_header.HB0 = 0;
>> +psr_vsc.sdp_header.HB1 = 0x7;
>> +psr_vsc.sdp_header.HB2 = 0x2;
>> +psr_vsc.sdp_header.HB3 = 0x8;
>> +
>> +psr_vsc.DB0 = 0;
>> +psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | 
>> EDP_VSC_PSR_CRC_VALUES_VALID;
>> +
>> +analogix_dp_send_psr_spd(dp, _vsc);
>> +return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
>> +
>> +int analogix_dp_disable_psr(struct device *dev)
>> +{
>> +struct analogix_dp_device *dp = dev_get_drvdata(dev);
>> +struct edp_vsc_psr psr_vsc;
>> +
>> +if (!dp->psr_support)
>> +return -EINVAL;
>> +
>> +/* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
>> +memset(_vsc, 0, sizeof(psr_vsc));
>> +psr_vsc.sdp_header.HB0 = 0;
>> +psr_vsc.sdp_

[PATCH v2 6/6] drm/rockchip: Enable vblank without event

2016-08-17 Thread Yakir Yang
Sean,

On 08/17/2016 09:11 AM, Sean Paul wrote:
> vblank should be enabled regardless of whether an event
> is expected back. This is especially important for a cursor
> plane.
Yep, I also found that sometimes vblank haven't been enabled when I move 
the mouse lightly, that would cause eDP panel wound't exit from PSR 
active state, and then nothing would be updated on panel. After apply 
this patch, things work rightly now, thanks for fixing.

Reviewed-by: Yakir Yang 
Tested-by: Yakir Yang 
> Signed-off-by: Sean Paul 
> ---
>
> Changes in v2:
>   - Rebased on 
> https://cgit.freedesktop.org/~seanpaul/dogwood/log/?h=for-next
>
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 ++-
>   1 file changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index d1e0e06..1787084 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -112,6 +112,7 @@ struct vop {
>   struct device *dev;
>   struct drm_device *drm_dev;
>   bool is_enabled;
> + bool vblank_active;
>   
>   /* mutex vsync_ work */
>   struct mutex vsync_mutex;
> @@ -1107,10 +1108,11 @@ static void vop_crtc_atomic_begin(struct drm_crtc 
> *crtc,
>   struct vop *vop = to_vop(crtc);
>   
>   spin_lock_irq(>dev->event_lock);
> - if (crtc->state->event) {
> - WARN_ON(drm_crtc_vblank_get(crtc) != 0);
> - WARN_ON(vop->event);
> + vop->vblank_active = true;
> + WARN_ON(drm_crtc_vblank_get(crtc) != 0);
> + WARN_ON(vop->event);
>   
> + if (crtc->state->event) {
>   vop->event = crtc->state->event;
>   crtc->state->event = NULL;
>   }
> @@ -1197,12 +1199,14 @@ static void vop_handle_vblank(struct vop *vop)
>   
>   spin_lock_irqsave(>event_lock, flags);
>   if (vop->event) {
> -
>   drm_crtc_send_vblank_event(crtc, vop->event);
> - drm_crtc_vblank_put(crtc);
>   vop->event = NULL;
>   
>   }
> + if (vop->vblank_active) {
> + vop->vblank_active = false;
> + drm_crtc_vblank_put(crtc);
> + }
>   spin_unlock_irqrestore(>event_lock, flags);
>   
>   if (!completion_done(>wait_update_complete))
> @@ -1472,6 +1476,7 @@ static int vop_initial(struct vop *vop)
>   clk_disable(vop->aclk);
>   
>   vop->is_enabled = false;
> + vop->vblank_active = false;
>   
>   return 0;
>   




[PATCH v2 0/6] drm/rockchip: Some patches to update the PSR series

2016-08-17 Thread Yakir Yang
Sean,


On 08/17/2016 10:45 AM, Sean Paul wrote:
>
> On Aug 16, 2016 7:41 PM, "Yakir Yang"  <mailto:ykk at rock-chips.com>> wrote:
> >
> > Sean,
> >
> > Thanks a lot for your good fixes. I have reviewed most of them, and 
> all looks good to me.
> >
> > But I got a question for merging things. My PSR patch set still 
> under reviewing, haven't been picked up Mark or other maintainers.
>
> I've picked them up in my tree. I'll send a pull request to Dave once 
> all of the dependencies have been reviewed (marked NEEDS REVIEW).
>

Got it, thanks.

- Yakir

> Sean
>
> > Feel a little bit embarrassed, how could we handle this situation ?
> >
> > - Yakir
> >
> >
> > On 08/17/2016 09:11 AM, Sean Paul wrote:
> >>
> >> This is a follow-on set to Yakir's original PSR set here:
> >> https://lkml.org/lkml/2016/7/24/34
> >> and applies to the for-next branch at:
> >> https://cgit.freedesktop.org/~seanpaul/dogwood 
> <https://cgit.freedesktop.org/%7Eseanpaul/dogwood>
> >>
> >> There are a few issues with the code that needed to be
> >> shored up.
> >>   (1) The use of mutexes instead of spinlocks caused issues calling the
> >>   psr functions from vblank_enable/disable.
> >>   (2) The proliferation of workers due to (1)
> >>   (3) A bunch of races due to (2)
> >>   (4) vblank is not enabled unless an event is requested, this breaks
> >>   a lot of things, but most noticeable was cursor.
> >>
> >> Changes in v2:
> >> - Rebased on https://cgit.freedesktop.org/~seanpaul/dogwood 
> <https://cgit.freedesktop.org/%7Eseanpaul/dogwood>
> >>   instead of random on-list patches (some of which had drifted)
> >> - Added the "small fixes" patch to catch some nits
> >>
> >>
> >> Sean Paul (6):
> >>drm/rockchip: Convert psr_list_mutex to spinlock and use it
> >>drm/rockchip: Don't use a delayed worker for psr state changes
> >>drm/rockchip: Use a spinlock to protect psr state
> >>drm/rockchip: A couple small fixes to psr
> >>drm/rockchip: Improve analogix-dp psr handling
> >>drm/rockchip: Enable vblank without event
> >>
> >>   drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 19 --
> >>   drivers/gpu/drm/rockchip/rockchip_drm_drv.c |  2 +-
> >>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  2 +-
> >>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 90 
> -
> >>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 +++--
> >>   5 files changed, 69 insertions(+), 59 deletions(-)
> >>
> >
> >
>

-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160817/6767c7a5/attachment.html>


[PATCH v2 0/6] drm/rockchip: Some patches to update the PSR series

2016-08-17 Thread Yakir Yang
Sean,

On 08/17/2016 10:41 AM, Yakir Yang wrote:
> Sean,
>
> Thanks a lot for your good fixes. I have reviewed most of them, and 
> all looks good to me.
>
> But I got a question for merging things. My PSR patch set still under 
> reviewing, haven't been picked up Mark or other maintainers. Feel a 
> little bit embarrassed, how could we handle this situation ?
>
> - Yakir
>
> On 08/17/2016 09:11 AM, Sean Paul wrote:
>> This is a follow-on set to Yakir's original PSR set here:
>>  https://lkml.org/lkml/2016/7/24/34
>> and applies to the for-next branch at:
>> https://cgit.freedesktop.org/~seanpaul/dogwood

Oops, sorry for missing this comment, do you mean my PSR patch already 
have been site on your tree  :-D

- Yakir
>>
>> There are a few issues with the code that needed to be
>> shored up.
>>   (1) The use of mutexes instead of spinlocks caused issues calling the
>>   psr functions from vblank_enable/disable.
>>   (2) The proliferation of workers due to (1)
>>   (3) A bunch of races due to (2)
>>   (4) vblank is not enabled unless an event is requested, this breaks
>>   a lot of things, but most noticeable was cursor.
>>
>> Changes in v2:
>> - Rebased on https://cgit.freedesktop.org/~seanpaul/dogwood
>>   instead of random on-list patches (some of which had drifted)
>> - Added the "small fixes" patch to catch some nits
>>
>>
>> Sean Paul (6):
>>drm/rockchip: Convert psr_list_mutex to spinlock and use it
>>drm/rockchip: Don't use a delayed worker for psr state changes
>>drm/rockchip: Use a spinlock to protect psr state
>>drm/rockchip: A couple small fixes to psr
>>drm/rockchip: Improve analogix-dp psr handling
>>drm/rockchip: Enable vblank without event
>>
>>   drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 19 --
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.c |  2 +-
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  2 +-
>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 90 
>> -
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 +++--
>>   5 files changed, 69 insertions(+), 59 deletions(-)
>>
>




[PATCH v2 0/6] drm/rockchip: Some patches to update the PSR series

2016-08-17 Thread Yakir Yang
Sean,

Thanks a lot for your good fixes. I have reviewed most of them, and all 
looks good to me.

But I got a question for merging things. My PSR patch set still under 
reviewing, haven't been picked up Mark or other maintainers. Feel a 
little bit embarrassed, how could we handle this situation ?

- Yakir

On 08/17/2016 09:11 AM, Sean Paul wrote:
> This is a follow-on set to Yakir's original PSR set here:
>  https://lkml.org/lkml/2016/7/24/34
> and applies to the for-next branch at:
>   https://cgit.freedesktop.org/~seanpaul/dogwood
>
> There are a few issues with the code that needed to be
> shored up.
>   (1) The use of mutexes instead of spinlocks caused issues calling the
>   psr functions from vblank_enable/disable.
>   (2) The proliferation of workers due to (1)
>   (3) A bunch of races due to (2)
>   (4) vblank is not enabled unless an event is requested, this breaks
>   a lot of things, but most noticeable was cursor.
>
> Changes in v2:
>   - Rebased on https://cgit.freedesktop.org/~seanpaul/dogwood
> instead of random on-list patches (some of which had drifted)
>   - Added the "small fixes" patch to catch some nits
>
>
> Sean Paul (6):
>drm/rockchip: Convert psr_list_mutex to spinlock and use it
>drm/rockchip: Don't use a delayed worker for psr state changes
>drm/rockchip: Use a spinlock to protect psr state
>drm/rockchip: A couple small fixes to psr
>drm/rockchip: Improve analogix-dp psr handling
>drm/rockchip: Enable vblank without event
>
>   drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 19 --
>   drivers/gpu/drm/rockchip/rockchip_drm_drv.c |  2 +-
>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  2 +-
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 90 
> -
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 +++--
>   5 files changed, 69 insertions(+), 59 deletions(-)
>




[PATCH v2 5/6] drm/rockchip: Improve analogix-dp psr handling

2016-08-17 Thread Yakir Yang

On 08/17/2016 09:11 AM, Sean Paul wrote:
> Remove the delayed worker, opting instead for the non-delayed
> variety. Also introduce a lock to ensure we don't have races
> with the worker and psr_state. Finally, cancel and wait for
> the worker to finish when disabling the bridge.
>
> Signed-off-by: Sean Paul 
Reviewed-by: Yakir Yang 
> ---
>
> Changes in v2:
>   - Rebased on 
> https://cgit.freedesktop.org/~seanpaul/dogwood/log/?h=for-next
>
>   drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 19 ++-
>   1 file changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
> b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> index d6d0751..439b933 100644
> --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
> @@ -42,7 +42,6 @@
>   
>   #define HIWORD_UPDATE(val, mask)(val | (mask) << 16)
>   
> -#define PSR_SET_DELAY_TIME   msecs_to_jiffies(10)
>   #define PSR_WAIT_LINE_FLAG_TIMEOUT_MS   100
>   
>   #define to_dp(nm)   container_of(nm, struct rockchip_dp_device, nm)
> @@ -72,7 +71,8 @@ struct rockchip_dp_device {
>   struct regmap*grf;
>   struct reset_control *rst;
>   
> - struct delayed_work  psr_work;
> + struct work_struct   psr_work;
> + spinlock_t   psr_lock;
>   unsigned int psr_state;
>   
>   const struct rockchip_dp_chip_data *data;
> @@ -83,25 +83,29 @@ struct rockchip_dp_device {
>   static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
>   {
>   struct rockchip_dp_device *dp = to_dp(encoder);
> + unsigned long flags;
>   
>   dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
>   
> + spin_lock_irqsave(>psr_lock, flags);
>   if (enabled)
>   dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
>   else
>   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
>   
> - schedule_delayed_work(>psr_work, PSR_SET_DELAY_TIME);
> + schedule_work(>psr_work);
> + spin_unlock_irqrestore(>psr_lock, flags);
>   }
>   
>   static void analogix_dp_psr_work(struct work_struct *work)
>   {
>   struct rockchip_dp_device *dp =
> - container_of(work, typeof(*dp), psr_work.work);
> + container_of(work, typeof(*dp), psr_work);
>   struct drm_crtc *crtc = dp->encoder.crtc;
>   int psr_state = dp->psr_state;
>   int vact_end;
>   int ret;
> + unsigned long flags;
>   
>   if (!crtc)
>   return;
> @@ -115,10 +119,12 @@ static void analogix_dp_psr_work(struct work_struct 
> *work)
>   return;
>   }
>   
> + spin_lock_irqsave(>psr_lock, flags);
>   if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
>   analogix_dp_enable_psr(dp->dev);
>   else
>   analogix_dp_disable_psr(dp->dev);
> + spin_unlock_irqrestore(>psr_lock, flags);
>   }
>   
>   static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
> @@ -135,6 +141,8 @@ static int rockchip_dp_poweron(struct 
> analogix_dp_plat_data *plat_data)
>   struct rockchip_dp_device *dp = to_dp(plat_data);
>   int ret;
>   
> + cancel_work_sync(>psr_work);
> +
>   ret = clk_prepare_enable(dp->pclk);
>   if (ret < 0) {
>   dev_err(dp->dev, "failed to enable pclk %d\n", ret);
> @@ -390,8 +398,9 @@ static int rockchip_dp_bind(struct device *dev, struct 
> device *master,
>   dp->plat_data.power_off = rockchip_dp_powerdown;
>   dp->plat_data.get_modes = rockchip_dp_get_modes;
>   
> + spin_lock_init(>psr_lock);
>   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
> - INIT_DELAYED_WORK(>psr_work, analogix_dp_psr_work);
> + INIT_WORK(>psr_work, analogix_dp_psr_work);
>   
>   rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
>   




[PATCH v2 4/6] drm/rockchip: A couple small fixes to psr

2016-08-17 Thread Yakir Yang

On 08/17/2016 09:11 AM, Sean Paul wrote:
> A few things that need tidying up, no functional changes.
>
> Signed-off-by: Sean Paul 
Reviewed-by: Yakir Yang 
> ---
>
> Changes in v2:
>   - Introduced
>
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 19 +++
>   1 file changed, 7 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> index 5bd54f2..c6ac5d0 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> @@ -62,27 +62,25 @@ static void psr_set_state_locked(struct psr_drv *psr, 
> enum psr_state state)
>* Allowed finite state machine:
>*
>*   PSR_ENABLE  < = = = = = >  PSR_FLUSH
> -   *  | ^|
> -   *  | ||
> -   *  v ||
> +  *   | ^|
> +  *   | ||
> +  *   v ||
>*   PSR_DISABLE < - - - - - - - - -
>*/
> -
> - /* Forbid no state change */
>   if (state == psr->state)
>   return;
>   
> - /* Forbid DISABLE change to FLUSH */
> + /* Requesting a flush when disabled is a noop */
>   if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
>   return;
>   
>   psr->state = state;
>   
> - /* Allow but no need hardware change, just need assign the state */
> + /* Already disabled in flush, change the state, but not the hardware */
>   if (state == PSR_DISABLE && psr->state == PSR_FLUSH)
>   return;
>   
> - /* Refact to hardware state change */
> + /* Actually commit the state change to hardware */
>   switch (psr->state) {
>   case PSR_ENABLE:
>   psr->set(psr->encoder, true);
> @@ -109,10 +107,7 @@ static void psr_flush_handler(unsigned long data)
>   struct psr_drv *psr = (struct psr_drv *)data;
>   unsigned long flags;
>   
> - if (!psr)
> - return;
> -
> - /* State changed between flush time, then keep it */
> + /* If the state has changed since we initiated the flush, do nothing */
>   spin_lock_irqsave(>lock, flags);
>   if (psr->state == PSR_FLUSH)
>   psr_set_state_locked(psr, PSR_ENABLE);




[PATCH v2 3/6] drm/rockchip: Use a spinlock to protect psr state

2016-08-17 Thread Yakir Yang

On 08/17/2016 09:11 AM, Sean Paul wrote:
> The handling of psr state is racey, shore that up with
> a per-psr driver lock.
>
> Signed-off-by: Sean Paul 
Reviewed-by: Yakir Yang 
> ---
>
> Changes in v2:
>   - Rebased on 
> https://cgit.freedesktop.org/~seanpaul/dogwood/log/?h=for-next
>
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 26 +-
>   1 file changed, 17 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> index 4c645d7..5bd54f2 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> @@ -30,6 +30,7 @@ struct psr_drv {
>   struct list_headlist;
>   struct drm_encoder  *encoder;
>   
> + spinlock_t  lock;
>   enum psr_state  state;
>   
>   struct timer_list   flush_timer;
> @@ -55,7 +56,7 @@ out:
>   return psr;
>   }
>   
> -static void psr_set_state(struct psr_drv *psr, enum psr_state state)
> +static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
>   {
>   /*
>* Allowed finite state machine:
> @@ -75,7 +76,6 @@ static void psr_set_state(struct psr_drv *psr, enum 
> psr_state state)
>   if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
>   return;
>   
> - /* Only wrote in this work, no need lock protection */
>   psr->state = state;
>   
>   /* Allow but no need hardware change, just need assign the state */
> @@ -95,18 +95,28 @@ static void psr_set_state(struct psr_drv *psr, enum 
> psr_state state)
>   }
>   }
>   
> +static void psr_set_state(struct psr_drv *psr, enum psr_state state)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(>lock, flags);
> + psr_set_state_locked(psr, state);
> + spin_unlock_irqrestore(>lock, flags);
> +}
> +
>   static void psr_flush_handler(unsigned long data)
>   {
>   struct psr_drv *psr = (struct psr_drv *)data;
> + unsigned long flags;
>   
>   if (!psr)
>   return;
>   
>   /* State changed between flush time, then keep it */
> - if (psr->state != PSR_FLUSH)
> - return;
> -
> - psr_set_state(psr, PSR_ENABLE);
> + spin_lock_irqsave(>lock, flags);
> + if (psr->state == PSR_FLUSH)
> + psr_set_state_locked(psr, PSR_ENABLE);
> + spin_unlock_irqrestore(>lock, flags);
>   }
>   
>   /**
> @@ -167,9 +177,6 @@ void rockchip_drm_psr_flush(struct drm_device *dev)
>   
>   spin_lock_irqsave(_drv->psr_list_lock, flags);
>   list_for_each_entry(psr, _drv->psr_list, list) {
> - if (psr->state == PSR_DISABLE)
> - continue;
> -
>   mod_timer(>flush_timer,
> round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
>   
> @@ -202,6 +209,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
>   return -ENOMEM;
>   
>   setup_timer(>flush_timer, psr_flush_handler, (unsigned long)psr);
> + spin_lock_init(>lock);
>   
>   psr->state = PSR_DISABLE;
>   psr->encoder = encoder;




[PATCH v2 2/6] drm/rockchip: Don't use a delayed worker for psr state changes

2016-08-17 Thread Yakir Yang

On 08/17/2016 09:11 AM, Sean Paul wrote:
> The delayed worker isn't needed and is racey. Remove it and do
> the state change in line.
>
> Signed-off-by: Sean Paul 
Reviewed-by: Yakir Yang 
Tested-by: Yakir Yang 
> ---
>
> Changes in v2:
>   - Rebased on 
> https://cgit.freedesktop.org/~seanpaul/dogwood/log/?h=for-next
>
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 38 
> -
>   1 file changed, 10 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> index bd25273..4c645d7 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> @@ -19,7 +19,6 @@
>   #include "rockchip_drm_psr.h"
>   
>   #define PSR_FLUSH_TIMEOUT   msecs_to_jiffies(3000) /* 3 seconds */
> -#define PSR_SET_DELAY_TIME   msecs_to_jiffies(10)
>   
>   enum psr_state {
>   PSR_FLUSH,
> @@ -31,11 +30,8 @@ struct psr_drv {
>   struct list_headlist;
>   struct drm_encoder  *encoder;
>   
> - enum psr_state  request_state;
>   enum psr_state  state;
>   
> - struct delayed_work state_work;
> -
>   struct timer_list   flush_timer;
>   
>   void (*set)(struct drm_encoder *encoder, bool enable);
> @@ -59,11 +55,8 @@ out:
>   return psr;
>   }
>   
> -static void psr_state_work(struct work_struct *work)
> +static void psr_set_state(struct psr_drv *psr, enum psr_state state)
>   {
> - struct psr_drv *psr = container_of(work, typeof(*psr), state_work.work);
> - enum psr_state request_state = psr->request_state;
> -
>   /*
>* Allowed finite state machine:
>*
> @@ -75,24 +68,22 @@ static void psr_state_work(struct work_struct *work)
>*/
>   
>   /* Forbid no state change */
> - if (request_state == psr->state)
> + if (state == psr->state)
>   return;
>   
>   /* Forbid DISABLE change to FLUSH */
> - if (request_state == PSR_FLUSH && psr->state == PSR_DISABLE)
> + if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
>   return;
>   
> + /* Only wrote in this work, no need lock protection */
> + psr->state = state;
> +
>   /* Allow but no need hardware change, just need assign the state */
> - if (request_state == PSR_DISABLE && psr->state == PSR_FLUSH) {
> - psr->state = request_state;
> + if (state == PSR_DISABLE && psr->state == PSR_FLUSH)
>   return;
> - }
> -
> - /* Only wrote in this work, no need lock protection */
> - psr->state = request_state;
>   
>   /* Refact to hardware state change */
> - switch (request_state) {
> + switch (psr->state) {
>   case PSR_ENABLE:
>   psr->set(psr->encoder, true);
>   break;
> @@ -104,13 +95,6 @@ static void psr_state_work(struct work_struct *work)
>   }
>   }
>   
> -static void psr_set_state(struct psr_drv *psr, enum psr_state state)
> -{
> - psr->request_state = state;
> -
> - schedule_delayed_work(>state_work, PSR_SET_DELAY_TIME);
> -}
> -
>   static void psr_flush_handler(unsigned long data)
>   {
>   struct psr_drv *psr = (struct psr_drv *)data;
> @@ -119,7 +103,7 @@ static void psr_flush_handler(unsigned long data)
>   return;
>   
>   /* State changed between flush time, then keep it */
> - if (psr->request_state != PSR_FLUSH)
> + if (psr->state != PSR_FLUSH)
>   return;
>   
>   psr_set_state(psr, PSR_ENABLE);
> @@ -183,7 +167,7 @@ void rockchip_drm_psr_flush(struct drm_device *dev)
>   
>   spin_lock_irqsave(_drv->psr_list_lock, flags);
>   list_for_each_entry(psr, _drv->psr_list, list) {
> - if (psr->request_state == PSR_DISABLE)
> + if (psr->state == PSR_DISABLE)
>   continue;
>   
>   mod_timer(>flush_timer,
> @@ -219,8 +203,6 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
>   
>   setup_timer(>flush_timer, psr_flush_handler, (unsigned long)psr);
>   
> - INIT_DELAYED_WORK(>state_work, psr_state_work);
> -
>   psr->state = PSR_DISABLE;
>   psr->encoder = encoder;
>   psr->set = psr_set;




[PATCH v2 1/6] drm/rockchip: Convert psr_list_mutex to spinlock and use it

2016-08-17 Thread Yakir Yang

On 08/17/2016 09:11 AM, Sean Paul wrote:
> This patch converts the psr_list_mutex to a spinlock and locks
> all access to psr_list to avoid races (however unlikely they
> were).
>
> Signed-off-by: Sean Paul 
Reviewed-by: Yakir Yang 
> ---
>
> Changes in v2:
>   - Rebased on 
> https://cgit.freedesktop.org/~seanpaul/dogwood/log/?h=for-next
>
>   drivers/gpu/drm/rockchip/rockchip_drm_drv.c |  2 +-
>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  2 +-
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 25 ++---
>   3 files changed, 20 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index b43fe5d9..76eaf1d 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -157,7 +157,7 @@ static int rockchip_drm_bind(struct device *dev)
>   drm_dev->dev_private = private;
>   
>   INIT_LIST_HEAD(>psr_list);
> - mutex_init(>psr_list_mutex);
> + spin_lock_init(>psr_list_lock);
>   
>   drm_mode_config_init(drm_dev);
>   
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> index 9c34c9e..5c69845 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
> @@ -63,7 +63,7 @@ struct rockchip_drm_private {
>   struct drm_atomic_state *state;
>   
>   struct list_head psr_list;
> - struct mutex psr_list_mutex;
> + spinlock_t psr_list_lock;
>   };
>   
>   int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> index a6d3bd25..bd25273 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> @@ -45,12 +45,18 @@ static struct psr_drv *find_psr_by_crtc(struct drm_crtc 
> *crtc)
>   {
>   struct rockchip_drm_private *drm_drv = crtc->dev->dev_private;
>   struct psr_drv *psr;
> + unsigned long flags;
>   
> - list_for_each_entry(psr, _drv->psr_list, list)
> + spin_lock_irqsave(_drv->psr_list_lock, flags);
> + list_for_each_entry(psr, _drv->psr_list, list) {
>   if (psr->encoder->crtc == crtc)
> - return psr;
> + goto out;
> + }
> + psr = ERR_PTR(-ENODEV);
>   
> - return ERR_PTR(-ENODEV);
> +out:
> + spin_unlock_irqrestore(_drv->psr_list_lock, flags);
> + return psr;
>   }
>   
>   static void psr_state_work(struct work_struct *work)
> @@ -173,7 +179,9 @@ void rockchip_drm_psr_flush(struct drm_device *dev)
>   {
>   struct rockchip_drm_private *drm_drv = dev->dev_private;
>   struct psr_drv *psr;
> + unsigned long flags;
>   
> + spin_lock_irqsave(_drv->psr_list_lock, flags);
>   list_for_each_entry(psr, _drv->psr_list, list) {
>   if (psr->request_state == PSR_DISABLE)
>   continue;
> @@ -183,6 +191,7 @@ void rockchip_drm_psr_flush(struct drm_device *dev)
>   
>   psr_set_state(psr, PSR_FLUSH);
>   }
> + spin_unlock_irqrestore(_drv->psr_list_lock, flags);
>   }
>   EXPORT_SYMBOL(rockchip_drm_psr_flush);
>   
> @@ -199,6 +208,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
>   {
>   struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
>   struct psr_drv *psr;
> + unsigned long flags;
>   
>   if (!encoder || !psr_set)
>   return -EINVAL;
> @@ -215,9 +225,9 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
>   psr->encoder = encoder;
>   psr->set = psr_set;
>   
> - mutex_lock(_drv->psr_list_mutex);
> + spin_lock_irqsave(_drv->psr_list_lock, flags);
>   list_add_tail(>list, _drv->psr_list);
> - mutex_unlock(_drv->psr_list_mutex);
> + spin_unlock_irqrestore(_drv->psr_list_lock, flags);
>   
>   return 0;
>   }
> @@ -235,8 +245,9 @@ void rockchip_drm_psr_unregister(struct drm_encoder 
> *encoder)
>   {
>   struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
>   struct psr_drv *psr, *n;
> + unsigned long flags;
>   
> - mutex_lock(_drv->psr_list_mutex);
> + spin_lock_irqsave(_drv->psr_list_lock, flags);
>   list_for_each_entry_safe(psr, n, _drv->psr_list, list) {
>   if (psr->encoder == encoder) {
>   del_timer(>flush_timer);
> @@ -244,6 +255,6 @@ void rockchip_drm_psr_unregister(struct drm_encoder 
> *encoder)
>   kfree(psr);
>   }
>   }
> - mutex_unlock(_drv->psr_list_mutex);
> + spin_unlock_irqrestore(_drv->psr_list_lock, flags);
>   }
>   EXPORT_SYMBOL(rockchip_drm_psr_unregister);




[PATCH] drm/rockchip: Properly adjust to a true clock in adjusted_mode

2016-08-09 Thread Yakir Yang
Sean,


On 08/09/2016 03:29 AM, Sean Paul wrote:
> From: Douglas Anderson 
>
> When fixing up the clock in vop_crtc_mode_fixup() we're not doing it
> quite correctly.  Specifically if we've got the true clock 26667 Hz,
> we'll perform this calculation:
> 26667 / 1000 => 26
>
> Later when we try to set the clock we'll do clk_set_rate(26 *
> 1000).  The common clock framework won't actually pick the proper clock
> in this case since it always wants clocks <= the specified one.
>
> Let's solve this by using DIV_ROUND_UP.
>
> Signed-off-by: Douglas Anderson 
> Signed-off-by: Sean Paul 

After discuss with Zheng Xing (Rockchip clock contributor), we think 
this patch looks good, so:

Reviewed-by: Yakir Yang 

> ---
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index 31744fe..1bbffaf 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -891,7 +891,8 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
>   struct vop *vop = to_vop(crtc);
>   
>   adjusted_mode->clock =
> - clk_round_rate(vop->dclk, mode->clock * 1000) / 1000;
> + DIV_ROUND_UP(clk_round_rate(vop->dclk, mode->clock * 1000),
> +  1000);
>   
>   return true;
>   }




[PATCH v2] drm/bridge: analogix_dp: Ensure the panel is properly prepared/unprepared

2016-08-09 Thread Yakir Yang
+ Archit


On 08/09/2016 02:53 AM, Sean Paul wrote:
> Instead of just preparing the panel on bind, actually prepare/unprepare
> during modeset/disable. The panel must be prepared in order to read hpd
> status and edid, so we need to keep state around the prepares in order
> to ensure we don't accidentally turn the panel off at the wrong time.
>
> Signed-off-by: Sean Paul 

Reviewed-by: Yakir Yang 

And I also tested this patch on RK3399 Kevin board, panel works rightly, so:
Tested-by: Yakir Yang 

Also add Archit into CC list, guess this patch should go through his 
drm_bridge's tree.

Thanks,
- Yakir

> ---
>
> Changes in v2:
>   - Added panel_is_modeset state/lock to avoid racing detect with modeset 
> (marcheu)
>   - Added prepare/unprepare in .get_modes (yakir)
>
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 101 
> ++---
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |   3 +
>   2 files changed, 93 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 32715da..47c449a 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -923,11 +923,63 @@ static void analogix_dp_commit(struct 
> analogix_dp_device *dp)
>   analogix_dp_start_video(dp);
>   }
>   
> +/*
> + * This function is a bit of a catch-all for panel preparation, hopefully
> + * simplifying the logic of functions that need to prepare/unprepare the 
> panel
> + * below.
> + *
> + * If @prepare is true, this function will prepare the panel. Conversely, if 
> it
> + * is false, the panel will be unprepared.
> + *
> + * If @is_modeset_prepare is true, the function will disregard the current 
> state
> + * of the panel and either prepare/unprepare the panel based on @prepare. 
> Once
> + * it finishes, it will update dp->panel_is_modeset to reflect the current 
> state
> + * of the panel.
> + */
> +static int analogix_dp_prepare_panel(struct analogix_dp_device *dp,
> +  bool prepare, bool is_modeset_prepare)
> +{
> + int ret = 0;
> +
> + if (!dp->plat_data->panel)
> + return 0;
> +
> + mutex_lock(>panel_lock);
> +
> + /*
> +  * Exit early if this is a temporary prepare/unprepare and we're already
> +  * modeset (since we neither want to prepare twice or unprepare early).
> +  */
> + if (dp->panel_is_modeset && !is_modeset_prepare)
> + goto out;
> +
> + if (prepare)
> + ret = drm_panel_prepare(dp->plat_data->panel);
> + else
> + ret = drm_panel_unprepare(dp->plat_data->panel);
> +
> + if (ret)
> + goto out;
> +
> + if (is_modeset_prepare)
> + dp->panel_is_modeset = prepare;
> +
> +out:
> + mutex_unlock(>panel_lock);
> + return ret;
> +}
> +
>   int analogix_dp_get_modes(struct drm_connector *connector)
>   {
>   struct analogix_dp_device *dp = to_dp(connector);
>   struct edid *edid = (struct edid *)dp->edid;
> - int num_modes = 0;
> + int ret, num_modes = 0;
> +
> + ret = analogix_dp_prepare_panel(dp, true, false);
> + if (ret) {
> + DRM_ERROR("Failed to prepare panel (%d)\n", ret);
> + return 0;
> + }
>   
>   if (analogix_dp_handle_edid(dp) == 0) {
>   drm_mode_connector_update_edid_property(>connector, edid);
> @@ -940,6 +992,10 @@ int analogix_dp_get_modes(struct drm_connector 
> *connector)
>   if (dp->plat_data->get_modes)
>   num_modes += dp->plat_data->get_modes(dp->plat_data, connector);
>   
> + ret = analogix_dp_prepare_panel(dp, false, false);
> + if (ret)
> + DRM_ERROR("Failed to unprepare panel (%d)\n", ret);
> +
>   return num_modes;
>   }
>   
> @@ -960,11 +1016,23 @@ enum drm_connector_status
>   analogix_dp_detect(struct drm_connector *connector, bool force)
>   {
>   struct analogix_dp_device *dp = to_dp(connector);
> + enum drm_connector_status status = connector_status_disconnected;
> + int ret;
>   
> - if (analogix_dp_detect_hpd(dp))
> + ret = analogix_dp_prepare_panel(dp, true, false);
> + if (ret) {
> + DRM_ERROR("Failed to prepare panel (%d)\n", ret);
>   return connector_status_disconnected;
> + }
> +
> + if (!analogix_dp_detect_hpd(dp))
> + status = connector_status_connected;
>   
> - return connector_status

[PATCH] drm/bridge: analogix_dp: Remove duplicated code v2

2016-08-08 Thread Yakir Yang
+ Archit

Tomeu,

Thanks for the update  :-)

But you have missed three tiny align problems, please see my inline 
notes, wish you could fix them. After that this patch looks good to me, so:

Reviewed-by: Yakir Yang 

I guess this patch should go through Archit's drm_bridge tree, so I 
added him into the CC list.


- Yakir


On 08/05/2016 08:59 PM, Tomeu Vizoso wrote:
> Remove code for reading the EDID and DPCD fields and use the helpers
> instead.
>
> Besides the obvious code reduction, other helpers are being added to the
> core that could be used in this driver and will be good to be able to
> use them instead of duplicating them.
>
> Signed-off-by: Tomeu Vizoso 
> Tested-by: Javier Martinez Canillas 
> Tested-by: Sean Paul 
> Cc: Javier Martinez Canillas 
> Cc: Mika Kahola 
> Cc: Yakir Yang 
> Cc: Daniel Vetter 
>
> v2:
>  - A bunch of good fixes from Sean and Yakir
>  - Moved the transfer function to analogix_dp_reg.c
>  - Removed reference to the EDID from the dp struct
> ---
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 263 
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  40 +-
>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 451 
> ++---
>   3 files changed, 204 insertions(+), 550 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 32715daf73cb..624fc4f44450 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -31,6 +31,7 @@
>   #include 
>   
>   #include "analogix_dp_core.h"
> +#include "analogix_dp_reg.h"
>   
>   #define to_dp(nm)   container_of(nm, struct analogix_dp_device, nm)
>   
> @@ -97,150 +98,21 @@ static int analogix_dp_detect_hpd(struct 
> analogix_dp_device *dp)
>   return 0;
>   }
>   
> -static unsigned char analogix_dp_calc_edid_check_sum(unsigned char 
> *edid_data)
> -{
> - int i;
> - unsigned char sum = 0;
> -
> - for (i = 0; i < EDID_BLOCK_LENGTH; i++)
> - sum = sum + edid_data[i];
> -
> - return sum;
> -}
> -
> -static int analogix_dp_read_edid(struct analogix_dp_device *dp)
> -{
> - unsigned char *edid = dp->edid;
> - unsigned int extend_block = 0;
> - unsigned char sum;
> - unsigned char test_vector;
> - int retval;
> -
> - /*
> -  * EDID device address is 0x50.
> -  * However, if necessary, you must have set upper address
> -  * into E-EDID in I2C device, 0x30.
> -  */
> -
> - /* Read Extension Flag, Number of 128-byte EDID extension blocks */
> - retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
> - EDID_EXTENSION_FLAG,
> - _block);
> - if (retval)
> - return retval;
> -
> - if (extend_block > 0) {
> - dev_dbg(dp->dev, "EDID data includes a single extension!\n");
> -
> - /* Read EDID data */
> - retval = analogix_dp_read_bytes_from_i2c(dp,
> - I2C_EDID_DEVICE_ADDR,
> - EDID_HEADER_PATTERN,
> - EDID_BLOCK_LENGTH,
> - [EDID_HEADER_PATTERN]);
> - if (retval != 0) {
> - dev_err(dp->dev, "EDID Read failed!\n");
> - return -EIO;
> - }
> - sum = analogix_dp_calc_edid_check_sum(edid);
> - if (sum != 0) {
> - dev_err(dp->dev, "EDID bad checksum!\n");
> - return -EIO;
> - }
> -
> - /* Read additional EDID data */
> - retval = analogix_dp_read_bytes_from_i2c(dp,
> - I2C_EDID_DEVICE_ADDR,
> - EDID_BLOCK_LENGTH,
> - EDID_BLOCK_LENGTH,
> - [EDID_BLOCK_LENGTH]);
> - if (retval != 0) {
> - dev_err(dp->dev, "EDID Read failed!\n");
> - return -EIO;
> - }
> - sum = analogix_dp_calc_edid_check_sum([EDID_BLOCK_LENGTH]);
> - if (sum != 0) {
> - dev_err(dp->dev, "EDID bad checksum!\n");
> - return -EIO;
> - }
> -
> - analogix_dp_read_byte_from_dpcd(d

[PATCH] drm/bridge: analogix_dp: Remove duplicated code

2016-08-05 Thread Yakir Yang
Tomeu,

o_O

Ignore my previous email, seems I make a mistaken about the email 
format, and mess up the patch format.

I have move my previous comments to this one :-)

On 08/04/2016 02:23 PM, Tomeu Vizoso wrote:
> Remove code for reading the EDID and DPCD fields and use the helpers
> instead.
>
> Besides the obvious code reduction, other helpers are being added to the
> core that could be used in this driver and will be good to be able to
> use them instead of duplicating them.
>
> Signed-off-by: Tomeu Vizoso 
> Cc: Javier Martinez Canillas 
> Cc: Mika Kahola 
> Cc: Yakir Yang 
> Cc: Daniel Vetter 
> ---
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 390 
> +++--
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  39 +--
>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 324 -
>   3 files changed, 201 insertions(+), 552 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 32715daf73cb..c81cb37e56b6 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -31,6 +31,7 @@
>   #include 
>   
>   #include "analogix_dp_core.h"
> +#include "analogix_dp_reg.h"
>   
>   #define to_dp(nm)   container_of(nm, struct analogix_dp_device, nm)
>   
> @@ -97,150 +98,21 @@ static int analogix_dp_detect_hpd(struct 
> analogix_dp_device *dp)
>   return 0;
>   }
>   
> -static unsigned char analogix_dp_calc_edid_check_sum(unsigned char 
> *edid_data)
> -{
> - int i;
> - unsigned char sum = 0;
> -
> - for (i = 0; i < EDID_BLOCK_LENGTH; i++)
> - sum = sum + edid_data[i];
> -
> - return sum;
> -}
> -
> -static int analogix_dp_read_edid(struct analogix_dp_device *dp)
> -{
> - unsigned char *edid = dp->edid;
> - unsigned int extend_block = 0;
> - unsigned char sum;
> - unsigned char test_vector;
> - int retval;
> -
> - /*
> -  * EDID device address is 0x50.
> -  * However, if necessary, you must have set upper address
> -  * into E-EDID in I2C device, 0x30.
> -  */
> -
> - /* Read Extension Flag, Number of 128-byte EDID extension blocks */
> - retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
> - EDID_EXTENSION_FLAG,
> - _block);
> - if (retval)
> - return retval;
> -
> - if (extend_block > 0) {
> - dev_dbg(dp->dev, "EDID data includes a single extension!\n");
> -
> - /* Read EDID data */
> - retval = analogix_dp_read_bytes_from_i2c(dp,
> - I2C_EDID_DEVICE_ADDR,
> - EDID_HEADER_PATTERN,
> - EDID_BLOCK_LENGTH,
> - [EDID_HEADER_PATTERN]);
> - if (retval != 0) {
> - dev_err(dp->dev, "EDID Read failed!\n");
> - return -EIO;
> - }
> - sum = analogix_dp_calc_edid_check_sum(edid);
> - if (sum != 0) {
> - dev_err(dp->dev, "EDID bad checksum!\n");
> - return -EIO;
> - }
> -
> - /* Read additional EDID data */
> - retval = analogix_dp_read_bytes_from_i2c(dp,
> - I2C_EDID_DEVICE_ADDR,
> - EDID_BLOCK_LENGTH,
> - EDID_BLOCK_LENGTH,
> - [EDID_BLOCK_LENGTH]);
> - if (retval != 0) {
> - dev_err(dp->dev, "EDID Read failed!\n");
> - return -EIO;
> - }
> - sum = analogix_dp_calc_edid_check_sum([EDID_BLOCK_LENGTH]);
> - if (sum != 0) {
> - dev_err(dp->dev, "EDID bad checksum!\n");
> - return -EIO;
> - }
> -
> - analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
> - _vector);
> - if (test_vector & DP_TEST_LINK_EDID_READ) {
> - analogix_dp_write_byte_to_dpcd(dp,
> - DP_TEST_EDID_CHECKSUM,
> - edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
> - analogix_dp_write_byte_to_dpcd(dp,
> - DP_TEST_RESP

[PATCH] drm/bridge: analogix_dp: Remove duplicated code

2016-08-05 Thread Yakir Yang
Tomeu,

Nice job ! Have a few nits bellow.  ;)

On 08/04/2016 02:23 PM, Tomeu Vizoso wrote:
> Remove code for reading the EDID and DPCD fields and use the helpers
> instead.
>
> Besides the obvious code reduction, other helpers are being added to the
> core that could be used in this driver and will be good to be able to
> use them instead of duplicating them.
>
> Signed-off-by: Tomeu Vizoso 
> Cc: Javier Martinez Canillas 
> Cc: Mika Kahola 
> Cc: Yakir Yang 
> Cc: Daniel Vetter 
> ---
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 390 
> +++--
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  39 +--
>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 324 -
>   3 files changed, 201 insertions(+), 552 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 32715daf73cb..c81cb37e56b6 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -31,6 +31,7 @@
>   #include 
>   
>   #include "analogix_dp_core.h"
> +#include "analogix_dp_reg.h"
>   
>   #define to_dp(nm)   container_of(nm, struct analogix_dp_device, nm)
>   
> @@ -97,150 +98,21 @@ static int analogix_dp_detect_hpd(struct 
> analogix_dp_device *dp)
>   return 0;
>   }
>   
> -static unsigned char analogix_dp_calc_edid_check_sum(unsigned char 
> *edid_data)
> -{
> - int i;
> - unsigned char sum = 0;
> -
> - for (i = 0; i < EDID_BLOCK_LENGTH; i++)
> - sum = sum + edid_data[i];
> -
> - return sum;
> -}
> -
> -static int analogix_dp_read_edid(struct analogix_dp_device *dp)
> -{
> - unsigned char *edid = dp->edid;
> - unsigned int extend_block = 0;
> - unsigned char sum;
> - unsigned char test_vector;
> - int retval;
> -
> - /*
> -  * EDID device address is 0x50.
> -  * However, if necessary, you must have set upper address
> -  * into E-EDID in I2C device, 0x30.
> -  */
> -
> - /* Read Extension Flag, Number of 128-byte EDID extension blocks */
> - retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
> - EDID_EXTENSION_FLAG,
> - _block);
> - if (retval)
> - return retval;
> -
> - if (extend_block > 0) {
> - dev_dbg(dp->dev, "EDID data includes a single extension!\n");
> -
> - /* Read EDID data */
> - retval = analogix_dp_read_bytes_from_i2c(dp,
> - I2C_EDID_DEVICE_ADDR,
> - EDID_HEADER_PATTERN,
> - EDID_BLOCK_LENGTH,
> - [EDID_HEADER_PATTERN]);
> - if (retval != 0) {
> - dev_err(dp->dev, "EDID Read failed!\n");
> - return -EIO;
> - }
> - sum = analogix_dp_calc_edid_check_sum(edid);
> - if (sum != 0) {
> - dev_err(dp->dev, "EDID bad checksum!\n");
> - return -EIO;
> - }
> -
> - /* Read additional EDID data */
> - retval = analogix_dp_read_bytes_from_i2c(dp,
> - I2C_EDID_DEVICE_ADDR,
> - EDID_BLOCK_LENGTH,
> - EDID_BLOCK_LENGTH,
> - [EDID_BLOCK_LENGTH]);
> - if (retval != 0) {
> - dev_err(dp->dev, "EDID Read failed!\n");
> - return -EIO;
> - }
> - sum = analogix_dp_calc_edid_check_sum([EDID_BLOCK_LENGTH]);
> - if (sum != 0) {
> - dev_err(dp->dev, "EDID bad checksum!\n");
> - return -EIO;
> - }
> -
> - analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
> - _vector);
> - if (test_vector & DP_TEST_LINK_EDID_READ) {
> - analogix_dp_write_byte_to_dpcd(dp,
> - DP_TEST_EDID_CHECKSUM,
> - edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
> - analogix_dp_write_byte_to_dpcd(dp,
> - DP_TEST_RESPONSE,
> - DP_TEST_EDID_CHECKSUM_WRITE);
> - }
> - } else {
> - dev

[PATCH 1/3] drm/rockchip: inno_hdmi: add audio support

2016-08-04 Thread Yakir Yang
Mark,


Got it, would rebase soonest :-)


Thanks,
- Yakir

On 08/04/2016 10:01 AM, Mark yao wrote:
> Hi Yakir
>
> After apply your patch, I got following warning messge:
>
> drivers/gpu/drm/rockchip/inno_hdmi.c:818:2: warning: initialization 
> from incompatible pointer type [enabled by default]
> drivers/gpu/drm/rockchip/inno_hdmi.c:818:2: warning: (near 
> initialization for 'audio_codec_ops.hw_params') [enabled by default]
> drivers/gpu/drm/rockchip/inno_hdmi.c:819:2: warning: initialization 
> from incompatible pointer type [enabled by default]
> drivers/gpu/drm/rockchip/inno_hdmi.c:819:2: warning: (near 
> initialization for 'audio_codec_ops.audio_shutdown') [enabled by default]
> drivers/gpu/drm/rockchip/inno_hdmi.c:820:2: warning: initialization 
> from incompatible pointer type [enabled by default]
> drivers/gpu/drm/rockchip/inno_hdmi.c:820:2: warning: (near 
> initialization for 'audio_codec_ops.digital_mute') [enabled by default]
> drivers/gpu/drm/rockchip/inno_hdmi.c:821:2: warning: initialization 
> from incompatible pointer type [enabled by default]
> drivers/gpu/drm/rockchip/inno_hdmi.c:821:2: warning: (near 
> initialization for 'audio_codec_ops.get_eld') [enabled by default]
>
> since the commit "efc9194 ASoC: hdmi-codec: callback function will be 
> called with private data",
> the hdmi_codec_ops had some changes.
> Can you rebase your patch to the newest kernel?
>
> Thanks.
> On 2016年06月15日 21:28, Yakir Yang wrote:
>> Using the common hdmi-codec driver to support hdmi audio function.
>>
>> Signed-off-by: Yakir Yang 
>> ---
>>   drivers/gpu/drm/rockchip/inno_hdmi.c | 237 
>> ++-
>>   drivers/gpu/drm/rockchip/inno_hdmi.h |   2 +
>>   2 files changed, 237 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c 
>> b/drivers/gpu/drm/rockchip/inno_hdmi.c
>> index f8b4feb..c31dc07 100644
>> --- a/drivers/gpu/drm/rockchip/inno_hdmi.c
>> +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
>> @@ -29,6 +29,8 @@
>>   #include 
>>   #include 
>>   +#include 
>> +
>>   #include "rockchip_drm_drv.h"
>>   #include "rockchip_drm_vop.h"
>>   @@ -36,6 +38,12 @@
>> #define to_inno_hdmi(x)container_of(x, struct inno_hdmi, x)
>>   +struct audio_info {
>> +int sample_rate;
>> +int channels;
>> +int sample_width;
>> +};
>> +
>>   struct hdmi_data_info {
>>   int vic;
>>   bool sink_is_hdmi;
>> @@ -71,6 +79,9 @@ struct inno_hdmi {
>> unsigned int tmds_rate;
>>   +struct platform_device *audio_pdev;
>> +bool audio_enable;
>> +
>>   struct hdmi_data_infohdmi_data;
>>   struct drm_display_mode previous_mode;
>>   };
>> @@ -306,6 +317,57 @@ static int inno_hdmi_config_video_avi(struct 
>> inno_hdmi *hdmi,
>>   return inno_hdmi_upload_frame(hdmi, rc, , INFOFRAME_AVI, 
>> 0, 0, 0);
>>   }
>>   +static int inno_hdmi_config_audio_aai(struct inno_hdmi *hdmi,
>> +  struct audio_info *audio)
>> +{
>> +struct hdmi_audio_infoframe *faudio;
>> +union hdmi_infoframe frame;
>> +int rc;
>> +
>> +rc = hdmi_audio_infoframe_init();
>> +faudio = (struct hdmi_audio_infoframe *)
>> +
>> +faudio->channels = audio->channels;
>> +
>> +switch (audio->sample_width) {
>> +case 16:
>> +faudio->sample_size = HDMI_AUDIO_SAMPLE_SIZE_16;
>> +break;
>> +case 20:
>> +faudio->sample_size = HDMI_AUDIO_SAMPLE_SIZE_20;
>> +break;
>> +case 24:
>> +faudio->sample_size = HDMI_AUDIO_SAMPLE_SIZE_24;
>> +break;
>> +}
>> +
>> +switch (audio->sample_rate) {
>> +case 32000:
>> +faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_32000;
>> +break;
>> +case 44100:
>> +faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_44100;
>> +break;
>> +case 48000:
>> +faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
>> +break;
>> +case 88200:
>> +faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_88200;
>> +break;
>> +case 96000:
>> +faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_96000;
>> +break;
>> +case 176400:
>> +faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_176400;
>> +break;
>> +case 192000

[PATCH 1/3] drm/rockchip: inno_hdmi: add audio support

2016-08-02 Thread Yakir Yang
Hi Mark & Heiko,

Ping..

Thanks,
- Yakir

On 06/15/2016 09:28 PM, Yakir Yang wrote:
> Using the common hdmi-codec driver to support hdmi audio function.
>
> Signed-off-by: Yakir Yang 
> ---
>   drivers/gpu/drm/rockchip/inno_hdmi.c | 237 
> ++-
>   drivers/gpu/drm/rockchip/inno_hdmi.h |   2 +
>   2 files changed, 237 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c 
> b/drivers/gpu/drm/rockchip/inno_hdmi.c
> index f8b4feb..c31dc07 100644
> --- a/drivers/gpu/drm/rockchip/inno_hdmi.c
> +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
> @@ -29,6 +29,8 @@
>   #include 
>   #include 
>   
> +#include 
> +
>   #include "rockchip_drm_drv.h"
>   #include "rockchip_drm_vop.h"
>   
> @@ -36,6 +38,12 @@
>   
>   #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x)
>   
> +struct audio_info {
> + int sample_rate;
> + int channels;
> + int sample_width;
> +};
> +
>   struct hdmi_data_info {
>   int vic;
>   bool sink_is_hdmi;
> @@ -71,6 +79,9 @@ struct inno_hdmi {
>   
>   unsigned int tmds_rate;
>   
> + struct platform_device *audio_pdev;
> + bool audio_enable;
> +
>   struct hdmi_data_info   hdmi_data;
>   struct drm_display_mode previous_mode;
>   };
> @@ -306,6 +317,57 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi 
> *hdmi,
>   return inno_hdmi_upload_frame(hdmi, rc, , INFOFRAME_AVI, 0, 0, 0);
>   }
>   
> +static int inno_hdmi_config_audio_aai(struct inno_hdmi *hdmi,
> +   struct audio_info *audio)
> +{
> + struct hdmi_audio_infoframe *faudio;
> + union hdmi_infoframe frame;
> + int rc;
> +
> + rc = hdmi_audio_infoframe_init();
> + faudio = (struct hdmi_audio_infoframe *)
> +
> + faudio->channels = audio->channels;
> +
> + switch (audio->sample_width) {
> + case 16:
> + faudio->sample_size = HDMI_AUDIO_SAMPLE_SIZE_16;
> + break;
> + case 20:
> + faudio->sample_size = HDMI_AUDIO_SAMPLE_SIZE_20;
> + break;
> + case 24:
> + faudio->sample_size = HDMI_AUDIO_SAMPLE_SIZE_24;
> + break;
> + }
> +
> + switch (audio->sample_rate) {
> + case 32000:
> + faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_32000;
> + break;
> + case 44100:
> + faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_44100;
> + break;
> + case 48000:
> + faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
> + break;
> + case 88200:
> + faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_88200;
> + break;
> + case 96000:
> + faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_96000;
> + break;
> + case 176400:
> + faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_176400;
> + break;
> + case 192000:
> + faudio->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_192000;
> + break;
> + }
> +
> + return inno_hdmi_upload_frame(hdmi, rc, , INFOFRAME_AAI, 0, 0, 0);
> +}
> +
>   static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
>   {
>   struct hdmi_data_info *data = >hdmi_data;
> @@ -478,8 +540,9 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi,
>   inno_hdmi_i2c_init(hdmi);
>   
>   /* Unmute video and audio output */
> - hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
> -   v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
> + hdmi_modb(hdmi, HDMI_AV_MUTE, m_VIDEO_BLACK, v_VIDEO_MUTE(0));
> + if (hdmi->audio_enable)
> + hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE, v_AUDIO_MUTE(0));
>   
>   return 0;
>   }
> @@ -616,6 +679,174 @@ static struct drm_connector_helper_funcs 
> inno_hdmi_connector_helper_funcs = {
>   .best_encoder = inno_hdmi_connector_best_encoder,
>   };
>   
> +int inno_hdmi_audio_config_set(struct inno_hdmi *hdmi, struct audio_info 
> *audio)
> +{
> + int rate, N, channel;
> +
> + if (audio->channels < 3)
> + channel = I2S_CHANNEL_1_2;
> + else if (audio->channels < 5)
> + channel = I2S_CHANNEL_3_4;
> + else if (audio->channels < 7)
> + channel = I2S_CHANNEL_5_6;
> + else
> + channel = I2S_CHANNEL_7_8;
> +
> + switch (audio->sample_rate) {
> + case 32000:
> + rate = AUDIO_32K;
&

[PATCH] drm/analogix_dp: Ensure the panel is properly prepared/unprepared

2016-08-01 Thread Yakir Yang
Sean,

On 07/30/2016 03:16 AM, Sean Paul wrote:
> Instead of just preparing the panel on bind, actually prepare/unprepare
> during modeset/disable. The panel must be prepared in order to read hpd
> status, so we need to refcount the prepares in order to ensure we don't
> accidentally turn the panel off at the wrong time.
>
> Signed-off-by: Sean Paul 
> ---
>
>
> Hi Yakir,
> This is what I was talking about upthread. I've tested it and it seems to be 
> working.
>
> What do you think?

Thanks for your patch, and it works. But I have introduced two 
questions, and I haven't found a way to fixed them.

> Sean
>
>
>
> drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 48 +-
>   1 file changed, 37 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 32715da..7b764a4 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -960,11 +960,27 @@ enum drm_connector_status
>   analogix_dp_detect(struct drm_connector *connector, bool force)
>   {
>   struct analogix_dp_device *dp = to_dp(connector);
> + enum drm_connector_status status = connector_status_disconnected;
> + int ret;
>   
> - if (analogix_dp_detect_hpd(dp))
> - return connector_status_disconnected;
> + if (dp->plat_data->panel && dp->dpms_mode != DRM_MODE_DPMS_ON) {
> + ret = drm_panel_prepare(dp->plat_data->panel);
> + if (ret) {
> + DRM_ERROR("failed to setup panel (%d)\n", ret);
> + return connector_status_disconnected;
> + }
> + }
> +
> + if (!analogix_dp_detect_hpd(dp))
> + status = connector_status_connected;
> +
> + if (dp->plat_data->panel && dp->dpms_mode != DRM_MODE_DPMS_ON) {
> + ret = drm_panel_unprepare(dp->plat_data->panel);
> + if (ret)
> + DRM_ERROR("failed to setup the panel ret = %d\n", ret);
> + }
>   
> - return connector_status_connected;
> + return status;

1. Panel would flicker at system boot time. Your patch would flash the 
panel power in connector->detect() function when dp->dpms_mode isn't 
DRM_MODE_DPMS_OFF. So when userspace keep detect the connector status in 
boot time, we could see panel would flicker (light up for a while, and 
turn off again, and keep loop for several time). I have copied some 
kernel logs:


[   11.065267] YKK - analogix_dp_detect:1052
[   11.729596] YKK - analogix_dp_get_modes:1016
[   11.737608] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   11.749229] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   11.760799] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   13.315962] YKK - analogix_dp_detect:1052
[   13.984702] YKK - analogix_dp_get_modes:1016
[   13.992977] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   14.004414] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   14.015842] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   14.183109] YKK - analogix_dp_bridge_pre_enable:1147
[   14.306301] rockchip-dp ff97.edp: Link Training Clock Recovery 
success
[   14.319130] rockchip-dp ff97.edp: Link Training success!
[   14.326388] rockchip-dp ff97.edp: wait SYS_CTL_2.
[   14.437247] rockchip-dp ff97.edp: Timeout of video streamclk ok
[   14.443585] rockchip-dp ff97.edp: unable to config video


>   }
>   
>   static void analogix_dp_connector_destroy(struct drm_connector *connector)
> @@ -1035,6 +1051,18 @@ static int analogix_dp_bridge_attach(struct drm_bridge 
> *bridge)
>   return 0;
>   }
>   
> +static void analogix_dp_bridge_pre_enable(struct drm_bridge *bridge)
> +{
> + struct analogix_dp_device *dp = bridge->driver_private;
> + int ret;
> +
> + if (dp->plat_data->panel) {
> + ret = drm_panel_prepare(dp->plat_data->panel);
> + if (ret)
> + DRM_ERROR("failed to setup the panel ret = %d\n", ret);
> + }

2. Driver would failed to read EDID in some case. Panel would only be 
powered up in bridge->pre_enable() function which later than 
connector->get_modes() function, and this would caused DPCD transfer 
failed in analogix_dp_handle_edid(). This seem won't caused too big 
issue, cause userspace would read EDID again after br

[PATCH] drm/analogix_dp: Ensure the panel is properly prepared/unprepared

2016-08-01 Thread Yakir Yang
Sean,

On 07/30/2016 03:16 AM, Sean Paul wrote:
> Instead of just preparing the panel on bind, actually prepare/unprepare
> during modeset/disable. The panel must be prepared in order to read hpd
> status, so we need to refcount the prepares in order to ensure we don't
> accidentally turn the panel off at the wrong time.
>
> Signed-off-by: Sean Paul 
> ---
>
>
> Hi Yakir,
> This is what I was talking about upthread. I've tested it and it seems to be 
> working.
>
> What do you think?

Thanks for your patch, and it works. But I have introduced two 
questions, and I haven't found a way to fixed them.

> Sean
>
>
>
> drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 48 +-
>   1 file changed, 37 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 32715da..7b764a4 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -960,11 +960,27 @@ enum drm_connector_status
>   analogix_dp_detect(struct drm_connector *connector, bool force)
>   {
>   struct analogix_dp_device *dp = to_dp(connector);
> + enum drm_connector_status status = connector_status_disconnected;
> + int ret;
>   
> - if (analogix_dp_detect_hpd(dp))
> - return connector_status_disconnected;
> + if (dp->plat_data->panel && dp->dpms_mode != DRM_MODE_DPMS_ON) {
> + ret = drm_panel_prepare(dp->plat_data->panel);
> + if (ret) {
> + DRM_ERROR("failed to setup panel (%d)\n", ret);
> + return connector_status_disconnected;
> + }
> + }
> +
> + if (!analogix_dp_detect_hpd(dp))
> + status = connector_status_connected;
> +
> + if (dp->plat_data->panel && dp->dpms_mode != DRM_MODE_DPMS_ON) {
> + ret = drm_panel_unprepare(dp->plat_data->panel);
> + if (ret)
> + DRM_ERROR("failed to setup the panel ret = %d\n", ret);
> + }
>   
> - return connector_status_connected;
> + return status;

1. Panel would flicker at system boot time. Your patch would flash the 
panel power in connector->detect() function when dp->dpms_mode isn't 
DRM_MODE_DPMS_OFF. So when userspace keep detect the connector status in 
boot time, we could see panel would flicker (light up for a while, and 
turn off again, and keep loop for several time). I have copied some 
kernel logs:


[   11.065267] YKK - analogix_dp_detect:1052
[   11.729596] YKK - analogix_dp_get_modes:1016
[   11.737608] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   11.749229] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   11.760799] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   13.315962] YKK - analogix_dp_detect:1052
[   13.984702] YKK - analogix_dp_get_modes:1016
[   13.992977] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   14.004414] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   14.015842] rockchip-dp ff97.edp: 
analogix_dp_read_bytes_from_dpcd: Aux Transaction fail!
[   14.183109] YKK - analogix_dp_bridge_pre_enable:1147
[   14.306301] rockchip-dp ff97.edp: Link Training Clock Recovery 
success
[   14.319130] rockchip-dp ff97.edp: Link Training success!
[   14.326388] rockchip-dp ff97.edp: wait SYS_CTL_2.
[   14.437247] rockchip-dp ff97.edp: Timeout of video streamclk ok
[   14.443585] rockchip-dp ff97.edp: unable to config video


>   }
>   
>   static void analogix_dp_connector_destroy(struct drm_connector *connector)
> @@ -1035,6 +1051,18 @@ static int analogix_dp_bridge_attach(struct drm_bridge 
> *bridge)
>   return 0;
>   }
>   
> +static void analogix_dp_bridge_pre_enable(struct drm_bridge *bridge)
> +{
> + struct analogix_dp_device *dp = bridge->driver_private;
> + int ret;
> +
> + if (dp->plat_data->panel) {
> + ret = drm_panel_prepare(dp->plat_data->panel);
> + if (ret)
> + DRM_ERROR("failed to setup the panel ret = %d\n", ret);
> + }

2. Driver would failed to read EDID in some case. Panel would only be 
powered up in bridge->pre_enable() function which later than 
connector->get_modes() function, and this would caused DPCD transfer 
failed in analogix_dp_handle_edid(). This seem won't caused too big 
issue, cause userspace would read EDID again after br

[PATCH v14 0/17] Add Analogix Core Display Port Driver

2016-08-01 Thread Yakir Yang

On 07/29/2016 04:38 PM, Tomeu Vizoso wrote:
> On 5 April 2016 at 04:06, Yakir Yang  wrote:
>> Hi Daniel,
>>
>>
>> On 03/31/2016 06:15 PM, Daniel Vetter wrote:
>>> On Mon, Feb 15, 2016 at 07:08:05PM +0800, Yakir Yang wrote:
>>>> Hi all,
>>>>
>>>> The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller
>>>> share the same IP, so a lot of parts can be re-used. I split the common
>>>> code into bridge directory, then rk3288 and exynos only need to keep
>>>> some platform code. Cause I can't find the exact IP name of exynos dp
>>>> controller, so I decide to name dp core driver with "analogix" which I
>>>> find in rk3288 eDP TRM
>>>>
>>>> But there are still three light registers setting different between
>>>> exynos and rk3288.
>>>> 1. RK3288 have five special pll registers which not indicate in exynos
>>>>  dp controller.
>>>> 2. The address of DP_PHY_PD(dp phy power manager register) are different
>>>>  between rk3288 and exynos.
>>>> 3. Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp
>>>> debug
>>>>  register).
>>>>
>>>> Due to Mark Yao have introduced the ATOMIC support to Rockchip drm, so
>>>> it's
>>>> okay to use the ATOMIC helpers functions in connector_funcs. No need to
>>>> splict
>>>> the connector init to platform driver anymore, and this is the biggest
>>>> change
>>>> since version 11.
>>>>
>>>> This v14 didn't have lots of new changes which seems not the correct time
>>>> to
>>>> upgrade the version number, but I have changed ordering of patches
>>>> (adding 2
>>>> more, and removing 2 out). Especially to prevent confusing people, so I
>>>> updated
>>>> the whole series.
>>> So I'm jumping into this part way late, but just noticed (well Thierry
>>> pointed this out to me) that the exynos dp driver reinvents all the dp and
>>> dp-aux helpers we already. That's somewhat okish for a private driver (and
>>> exynos has a reputation for that kind of stuff), but imo not ok for a
>>> shared driver.
>>>
>>> Not saying this should block merging this patch, but it really needs to be
>>> addressed. All the dp aux and edid read code in the current
>>> exynos_dp_core/reg.c files needs to be replaced with dp helpers and the
>>> core i2c edid reading code.
>>>
>>> Who's going to sign up to do this?
>>
>> Volunteer to that, after finish this thread, I would send new series to
>> switch to take use of dp helper.
> Hi Yakir,
>
> do you have plans to do this work in the short term? If not, I can tackle it.

Wow, that would be great if you like to tackle it  :-D

I always keep this in my mind, but haven't found an chance
to finish it. I would like to sit in your Cc list when you post
them out  ;)

Best Regards,
- Yakir

> Regards,
>
> Tomeu
>
>> :-D
>> - Yakir
>>
>>
>>> -Daniel
>>>
>>>> Thanks,
>>>> - Yakir
>>>>
>>>>
>>>> Changes in v14:
>>>> - Rebase the new changes in imx-dp driver
>>>> - Split up this patch into 3 parts, make this easy to review (Heiko)
>>>> - Remove the Rockchip DP PHY to an separate thread (Heiko)
>>>>   https://patchwork.kernel.org/patch/8312701/
>>>>
>>>> Changes in v13:
>>>> - Use .enable instead of preprare/commit in encoder_helper_funcs (Heiko)
>>>> - Fix the missing parameters with drm_encoder_init() helper function.
>>>> (Heiko)
>>>>
>>>> Changes in v12:
>>>> - Move the connector init to analogix_dp driver, and using ATOMIC helper
>>>> (Heiko)
>>>> - Add the ack from Jingoo
>>>> - Remove the enum link_rate_type struct, using the marcos in
>>>> drm_dp_helper.h (Jingoo)
>>>>
>>>> Changes in v11:
>>>> - Uses tabs to fix the indentation issues in analogix_dp_core.h (Heiko)
>>>> - Rename the "analogix,need-force-hpd" to common 'force-hpd' (Rob)
>>>> - Add the ack from Rob Herring
>>>> - Revert parts of Gustavo Padovan's changes in commit:
>>>>  drm/exynos: do not start enabling DP at bind() phase
>>>> Add dp phy poweron function in bind time.
>>>> - Move the panel prepare from get_modes time to bind time, and move
>>>> 

[PATCH v1 2/2] drm/bridge: analogix_dp: turn off the panel when eDP need to disable

2016-07-28 Thread Yakir Yang
Sean,

Oops, sorry about miss your suggest :(

On 07/22/2016 11:03 PM, Sean Paul wrote:
> On Thu, Jul 21, 2016 at 9:00 PM, Yakir Yang  wrote:
>> Sean,
>>
>> Thanks for your fast respond :-)
>>
>> But this patch is not the latest one, I have upgraded this to "v1.1" version
>> to fix the eDP can't be disabled problem:
>>  [PATCH v1.1 2/2] drm/bridge: analogix_dp: turn off the panel when eDP
>> need to disable
>>  Changes in v1.1: - unprepare the panel at the end of
>> bridge->disable() function
>>
>> In spite of this, I would take your comments with my "v1.1" patch.
>>
>> On 07/21/2016 10:28 PM, Sean Paul wrote:
>>
>> On Thu, Jul 21, 2016 at 9:14 AM, Yakir Yang  wrote:
>>
>> Some panels (like Sharp LQ123P1JX31) need to be turn off when eDP
>> controller stop to send valid video signal, otherwhise panel would
>> go burn in, and keep flicker and flicker.
>>
>> So it's better to turn off the panel when eDP need to disable, and
>> we need to turn on the panel in connector->detect() callback, so
>> that driver would detect panel status rightly.
>>
>> Signed-off-by: Yakir Yang 
>> ---
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 18 ++
>>   1 file changed, 10 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 32715da..ea059b3 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -961,6 +961,14 @@ analogix_dp_detect(struct drm_connector *connector,
>> bool force)
>>   {
>>  struct analogix_dp_device *dp = to_dp(connector);
>>
>> +   /*
>> +* Panle would prepare for several times here, but don't worry it
>>
>> s/Panle/Panel/
>>
>>
>> Done
>>
>> +* would only enable the hardware at the first prepare time.
>>
>> Errr, this shouldn't go in detect. How about putting this in
>> bridge_enable instead?
>>
>>
>> Nope, if we put this in bridge_enable, then eDP would never be enabled.
>> Here're the calling flow.
>>
>> --> analogix_dp_probe
>>--> analogix_dp_bind  # we still haven't prepared the panel here, that
>> means panel have been powered up
>>  --> analogix_dp_detect  # Oops, losing panel valid hotplug signal, cause
>> panel have been powered up
>>  --> ** Keep detecting **
>
> Yeah, after playing around with the patch yesterday I discovered this
> for myself. I still don't think detect() should be changing hardware
> state. Perhaps you could add a matching unprepare() after you attempt
> to detect the panel?

Hmm, I don't understand the meaning of "add a matching unprepare()".

I didn't see there is an unprepare() callback in drm_crtc_helper.h, would
you like to share some simple code :-D

Thanks,
- Yakir

> Sean
>
>> +*/
>> +   if (dp->plat_data->panel)
>> +   if (drm_panel_prepare(dp->plat_data->panel))
>>
>> Personally, I don't like doing work in a conditional since you're
>> throwing the return code away. Could you break this out into:
>>
>> ret = drm_panel_prepare(dp->plat_data->panel);
>> if (ret)
>>DRM_ERROR("failed to setup the panel ret=%d\n", ret);
>>
>>
>> Okay
>>
>>
>> +   DRM_ERROR("failed to setup the panel\n");
>> +
>>  if (analogix_dp_detect_hpd(dp))
>>  return connector_status_disconnected;
>>
>> @@ -1063,7 +1071,8 @@ static void analogix_dp_bridge_disable(struct
>> drm_bridge *bridge)
>>  return;
>>
>>  if (dp->plat_data->panel) {
>> -   if (drm_panel_disable(dp->plat_data->panel)) {
>> +   if (drm_panel_disable(dp->plat_data->panel) ||
>> +   drm_panel_unprepare(dp->plat_data->panel)) {
>>
>> Same comment here, please break this out into separate statements for
>> better readability/logging.
>>
>>
>> Okay,
>>
>>
>> Thanks,
>> - Yakir
>>
>>
>>  DRM_ERROR("failed to disable the panel\n");
>>  return;
>>  }
>> @@ -1333,13 +1342,6 @@ int analogix_dp_bind(struct device *dev, struct
>> drm_device *drm_dev,
>>
>>  phy_power_on(dp->phy);
>>
>> -   if (dp->plat_data->panel) {
>> -   if (drm_panel_prepare(dp->plat_data->panel)) {
>> -   DRM_ERROR("failed to setup the panel\n");
>> -   return -EBUSY;
>> -   }
>> -   }
>> -
>>  analogix_dp_init_dp(dp);
>>
>>  ret = devm_request_threaded_irq(>dev, dp->irq,
>> --
>> 1.9.1
>>
>>
>>
>>
>>
>
>




[PATCH v4 2/4] drm/rockchip: add an common abstracted PSR driver

2016-07-24 Thread Yakir Yang
Sean,

On 07/14/2016 11:14 PM, Sean Paul wrote:
> On Thu, Jul 14, 2016 at 12:15:49PM +0800, Yakir Yang wrote:
>> The PSR driver have exported four symbols for specific device driver:
>> - rockchip_drm_psr_register()
>> - rockchip_drm_psr_unregister()
>> - rockchip_drm_psr_enable()
>> - rockchip_drm_psr_disable()
>> - rockchip_drm_psr_flush()
>>
>> Encoder driver should call the register/unregister interfaces to hook
>> itself into common PSR driver, encoder have implement the 'psr_set'
>> callback which use the set PSR state in hardware side.
>>
>> Crtc driver would call the enable/disable interfaces when vblank is
>> enable/disable, after that the common PSR driver would call the encoder
>> registered callback to set the PSR state.
>>
>> Fb driver would call the flush interface in 'fb->dirty' callback, this
>> helper function would force all PSR enabled encoders to exit from PSR
>> for 3 seconds.
>>
>> Signed-off-by: Yakir Yang 
>
> I still don't think it's a good idea to pull this out into a separate PSR
> driver, but I suppose we can integrate it at a later time if it becomes
> cumbersome.
>
> Reviewed-by: Sean Paul 

In order to make it safely to call those symbols at interrupt context, i 
have made lots of changes about this patch. It's not suitable to take 
your reviewed flag at the v5, if you're happy to review the new one [0], 
that would be very nice  :-D

[0]: https://patchwork.kernel.org/patch/9244805/

Thanks,
- Yakir


>
>> ---
>> Changes in v4:
>> - Tuck the global "psr_list" & "psr_list_mutex" in struct 
>> rockchip_drm_private. (Sean)
>> - Move the access of "psr->state" under "psr->state_mutex"'s protect. (Sean)
>> - Let "psr->state = PSR_FLUSH" under "psr->state_mutex"'s protect. (Sean)
>> - Collect psr_enable() and psr_disable() into psr_set_state()
>> - s/5\ second/PSR_FLUSH_TIMEOUT/ (Sean)
>> - Flush the psr callback in vop_crtc_disable(). (Stéphane, reviewed in 
>> Google gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/349084/6/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>  at 475]
>> - Add the missing file head with license. (Stéphane, reviewed in Google 
>> gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/357563/1/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
>>  at 3]
>>
>> Changes in v3:
>> - split the psr flow into an common abstracted PSR driver
>> - implement the 'fb->dirty' callback function (Daniel)
>> - avoid to use notify to acqiure for vact event (Daniel)
>> - remove psr_active() callback which introduce in v2
>>
>> Changes in v2: None
>>
>>   drivers/gpu/drm/rockchip/Makefile   |   2 +-
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   4 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  12 ++
>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 223 
>> 
>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  26 
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  29 
>>   7 files changed, 298 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h
>>
>> diff --git a/drivers/gpu/drm/rockchip/Makefile 
>> b/drivers/gpu/drm/rockchip/Makefile
>> index 05d0713..9746365 100644
>> --- a/drivers/gpu/drm/rockchip/Makefile
>> +++ b/drivers/gpu/drm/rockchip/Makefile
>> @@ -3,7 +3,7 @@
>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>   
>>   rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
>> -rockchip_drm_gem.o rockchip_drm_vop.o
>> +rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
>>   rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>>   
>>   obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
>> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> index d665fb0..26c12b3 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> @@ -156,6 +156,9 @@ static int rockchip_drm_bind(struct device *dev)
>>   
>>  drm_dev->dev_private = private;
>>   
>> +INIT_LIST_HEAD(>psr_list);
>> +mutex_init(>psr_list_mutex);
>> +
>>  drm_mode_config_init(drm_dev);
>>   
>>  rockchip_drm_mode_config

[PATCH v4 2/4] drm/rockchip: add an common abstracted PSR driver

2016-07-24 Thread Yakir Yang
Doug,

On 07/23/2016 12:04 PM, Doug Anderson wrote:
> Yakir,
>
> On Wed, Jul 13, 2016 at 9:15 PM, Yakir Yang  wrote:
>> +static void psr_set_state(struct psr_drv *psr, enum psr_state state)
>> +{
>> +   mutex_lock(>state_mutex);
>> +
>> +   if (psr->state == state) {
>> +   mutex_unlock(>state_mutex);
>> +   return;
>> +   }
>> +
>> +   psr->state = state;
>> +   switch (state) {
>> +   case PSR_ENABLE:
>> +   psr->set(psr->encoder, true);
>> +   break;
>> +
>> +   case PSR_DISABLE:
>> +   case PSR_FLUSH:
>> +   psr->set(psr->encoder, false);
>> +   break;
>> +   };
>> +
>> +   mutex_unlock(>state_mutex);
>> +}
>> +
>> +static void psr_flush_handler(unsigned long data)
>> +{
>> +   struct psr_drv *psr = (struct psr_drv *)data;
>> +
>> +   if (!psr || psr->state != PSR_FLUSH)
>> +   return;
>> +
>> +   psr_set_state(psr, PSR_ENABLE);
> As mentioned in a separate thread, this is probably not OK.
> psr_set_state() grabs a mutex and that might sleep.  ...but
> psr_flush_handler() is a timer.  I'm nearly certain that timers can't
> sleep.
>
> I believe this is the source of "sleeping function called from invalid
> context" that I've seen at times.

Thanks for your reported, i have wrote a patch[0] to fix this problem in 
my v5. If you're happy to review, that would be great ;)

[0]: https://patchwork.kernel.org/patch/9244805/

- Yakir

>
> -Doug
>
>
>




[PATCH v5 4/4] drm/rockchip: analogix_dp: implement PSR function

2016-07-24 Thread Yakir Yang
Alway enable the PSR function for Rockchip analogix_dp driver. If panel
don't support PSR, then the core analogix_dp would ignore this setting.

Signed-off-by: Yakir Yang 
Reviewed-by: Sean Paul 
---
Changes in v5:
- Add reviewed flag from Sean.

Changes in v4:
- Return 'void' instead of 'int' in analogix_dp_psr_set(). (Sean)
- Pull the 10ms delay time out into a #define. (Sean)
- Improved the code of analogix_dp_psr_work(). (Sean)
- Indented with spaces for new numbers in rockchip_dp_device struct. 
(Stéphane, reviewed at Google gerrit)

[https://chromium-review.googlesource.com/#/c/349085/33/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 83]

Changes in v3:
- split the common psr logic into a seperate driver, make this to a
  simple sub-psr device driver.

Changes in v2:
- remove vblank notify out (Daniel)
- create a psr_active() callback in vop data struct.

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 57 +
 1 file changed, 57 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index e81e19a..aa916f4 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -32,6 +32,7 @@
 #include 

 #include "rockchip_drm_drv.h"
+#include "rockchip_drm_psr.h"
 #include "rockchip_drm_vop.h"

 #define RK3288_GRF_SOC_CON60x25c
@@ -41,6 +42,9 @@

 #define HIWORD_UPDATE(val, mask)   (val | (mask) << 16)

+#define PSR_SET_DELAY_TIME msecs_to_jiffies(10)
+#define PSR_WAIT_LINE_FLAG_TIMEOUT_MS  100
+
 #define to_dp(nm)  container_of(nm, struct rockchip_dp_device, nm)

 /**
@@ -68,11 +72,55 @@ struct rockchip_dp_device {
struct regmap*grf;
struct reset_control *rst;

+   struct delayed_work  psr_work;
+   unsigned int psr_state;
+
const struct rockchip_dp_chip_data *data;

struct analogix_dp_plat_data plat_data;
 };

+static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
+{
+   struct rockchip_dp_device *dp = to_dp(encoder);
+
+   dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
+
+   if (enabled)
+   dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
+   else
+   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
+
+   schedule_delayed_work(>psr_work, PSR_SET_DELAY_TIME);
+}
+
+static void analogix_dp_psr_work(struct work_struct *work)
+{
+   struct rockchip_dp_device *dp =
+   container_of(work, typeof(*dp), psr_work.work);
+   struct drm_crtc *crtc = dp->encoder.crtc;
+   int psr_state = dp->psr_state;
+   int vact_end;
+   int ret;
+
+   if (!crtc)
+   return;
+
+   vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
crtc->mode.vdisplay;
+
+   ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
+ PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
+   if (ret) {
+   dev_err(dp->dev, "line flag interrupt did not arrive\n");
+   return;
+   }
+
+   if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
+   analogix_dp_enable_psr(dp->dev);
+   else
+   analogix_dp_disable_psr(dp->dev);
+}
+
 static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
 {
reset_control_assert(dp->rst);
@@ -340,12 +388,21 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
dp->plat_data.power_off = rockchip_dp_powerdown;
dp->plat_data.get_modes = rockchip_dp_get_modes;

+   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
+   INIT_DELAYED_WORK(>psr_work, analogix_dp_psr_work);
+
+   rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
+
return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
 }

 static void rockchip_dp_unbind(struct device *dev, struct device *master,
   void *data)
 {
+   struct rockchip_dp_device *dp = dev_get_drvdata(dev);
+
+   rockchip_drm_psr_unregister(>encoder);
+
return analogix_dp_unbind(dev, master, data);
 }

-- 
1.9.1




[PATCH v5 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-24 Thread Yakir Yang
The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Signed-off-by: Yakir Yang 
Reviewed-by: Sean Paul 
---
Changes in v5:
- Add reviewed flag from Sean.

Changes in v4.1:
- Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
- Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
- Add comment about PBx magic numbers. (Sean)

Changes in v4:
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().

Changes in v3:
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments

Changes in v2:
- introduce in v2, splite the common Analogix DP changes out

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
 include/drm/bridge/analogix_dp.h   |  3 +
 5 files changed, 174 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..381b25e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }

+int analogix_dp_enable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
+
+int analogix_dp_disable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = 0;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
+
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_version;
+
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
+   dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
+
+   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
+}
+
+static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_en;
+
+   /* Disable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en &= ~DP_PSR_ENABLE;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Main-Link transmitter remains active during PSR active states */
+   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Enable psr function */
+   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
+DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   analogix_dp_enable_psr_crc(dp);
+}
+
 static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
 {
int i;
@@ -921,6 +998,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
*dp)

/* Enable video */
analogix_dp_start_video(dp);
+
+   dp->psr_support = analogix_dp_detect_sink_psr(dp);
+   if (dp->psr_support)
+   

[PATCH v5 2/4] drm/rockchip: add an common abstracted PSR driver

2016-07-24 Thread Yakir Yang
The PSR driver have exported four symbols for specific device driver, and
it's safe to call them in interrupt context:
- rockchip_drm_psr_register()
- rockchip_drm_psr_unregister()
- rockchip_drm_psr_enable()
- rockchip_drm_psr_disable()
- rockchip_drm_psr_flush()

Encoder driver should call the register/unregister interfaces to hook
itself into common PSR driver, encoder have implement the 'psr_set'
callback which use the set PSR state in hardware side.

Crtc driver would call the enable/disable interfaces when vblank is
enable/disable, after that the common PSR driver would call the encoder
registered callback to set the PSR state.

Fb driver would call the flush interface in 'fb->dirty' callback, this
helper function would force all PSR enabled encoders to exit from PSR
for 3 seconds.

Signed-off-by: Yakir Yang 
---
Changes in v5:
- Only keep 'psr_list_mutex' at register/unregister time.
- Remove unused global variables.
- Make list traversal safely at rockchip_drm_psr_unregister().
- Make psr_set_state() to a delay work, safe to call exported symbols at
  interrupt context.
- Remove the repeated psr delay work in vop driver.

Changes in v4:
- Tuck the global "psr_list" & "psr_list_mutex" in struct rockchip_drm_private. 
(Sean)
- Move the access of "psr->state" under "psr->state_mutex"'s protect. (Sean)
- Let "psr->state = PSR_FLUSH" under "psr->state_mutex"'s protect. (Sean)
- Collect psr_enable() and psr_disable() into psr_set_state()
- s/5\ second/PSR_FLUSH_TIMEOUT/ (Sean)
- Flush the psr callback in vop_crtc_disable(). (Stéphane, reviewed in Google 
gerrit)

[https://chromium-review.googlesource.com/#/c/349084/6/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 475]
- Add the missing file head with license. (Stéphane, reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/357563/1/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
 at 3]

Changes in v3:
- split the psr flow into an common abstracted PSR driver
- implement the 'fb->dirty' callback function (Daniel)
- avoid to use notify to acqiure for vact event (Daniel)
- remove psr_active() callback which introduce in v2

Changes in v2: None

 drivers/gpu/drm/rockchip/Makefile   |   2 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  12 ++
 drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 249 
 drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  26 +++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   9 +
 7 files changed, 303 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index 05d0713..9746365 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -3,7 +3,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-   rockchip_drm_gem.o rockchip_drm_vop.o
+   rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o

 obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index a822d49..b43fe5d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -156,6 +156,9 @@ static int rockchip_drm_bind(struct device *dev)

drm_dev->dev_private = private;

+   INIT_LIST_HEAD(>psr_list);
+   mutex_init(>psr_list_mutex);
+
drm_mode_config_init(drm_dev);

rockchip_drm_mode_config_init(drm_dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 239b830..9c34c9e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -61,6 +61,9 @@ struct rockchip_drm_private {
struct drm_gem_object *fbdev_bo;
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
struct drm_atomic_state *state;
+
+   struct list_head psr_list;
+   struct mutex psr_list_mutex;
 };

 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 55c5273..ba45d9d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -22,6 +22,7 @@
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
 #include "rockchip_drm_gem.h"
+#include "rockchip_drm_psr.h"

 #define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)

@@ -63

[PATCH v5 1/4] drm/rockchip: vop: export line flag function

2016-07-24 Thread Yakir Yang
VOP have integrated a hardware counter which indicate the exact display
line that vop is scanning. And if we're interested in a specific line,
we can set the line number to vop line_flag register, and then vop would
generate a line_flag interrupt for it.

For example eDP PSR function is interested in the vertical blanking
period, then driver could set the line number to zero.

This patch have exported a symbol that allow other driver to listen the
line flag event with given timeout limit:
-  rockchip_drm_wait_line_flag()

Signed-off-by: Yakir Yang 
Reviewed-by: Sean Paul 
---
Changes in v5:
- Add reviewed flag from Sean.

Changes in v4.1:
- Remove the completion_done() check in irq handler (Sean)

Changes in v4:
- Avoid the weird behavior in rockchip_drm_wait_line_flag(). (Sean)
- Make line_flag_num_x to an array. (Sean)
- Remove the unused vop_cfg_done() in vop_line_flag_irq_enable(). (Stephane, 
reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/349084/33/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 466]

Changes in v3:
- Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
- Add 'line_flag_num_0' for RK3288/RK3036
- Remove the notify for waiting line_flag event (Daniel)

Changes in v2:
- Introduce in v2, split VOP line flag changes out

 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 117 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   2 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   4 +
 4 files changed, 126 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..239b830 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -70,4 +70,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
+int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
+   unsigned int mstimeout);
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index bc08b50..90a7e62 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -121,6 +121,8 @@ struct vop {
/* protected by dev->event_lock */
struct drm_pending_vblank_event *event;

+   struct completion line_flag_completion;
+
const struct vop_data *data;

uint32_t *regsbak;
@@ -431,6 +433,71 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+/*
+ * (1) each frame starts at the start of the Vsync pulse which is signaled by
+ * the "FRAME_SYNC" interrupt.
+ * (2) the active data region of each frame ends at dsp_vact_end
+ * (3) we should program this same number (dsp_vact_end) into 
dsp_line_frag_num,
+ *  to get "LINE_FLAG" interrupt at the end of the active on screen data.
+ *
+ * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
+ * Interrupts
+ * LINE_FLAG ---+
+ * FRAME_SYNC + |
+ *| |
+ *v v
+ *| Vsync | Vbp |  Vactive  | Vfp |
+ *^ ^   ^ ^
+ *| |   | |
+ *| |   | |
+ * dsp_vs_end + |   | |   VOP_DSP_VTOTAL_VS_END
+ * dsp_vact_start --+   | |   VOP_DSP_VACT_ST_END
+ * dsp_vact_end + |   VOP_DSP_VACT_ST_END
+ * dsp_total -+   VOP_DSP_VTOTAL_VS_END
+ */
+static bool vop_line_flag_irq_is_enabled(struct vop *vop)
+{
+   uint32_t line_flag_irq;
+   unsigned long flags;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   line_flag_irq = VOP_INTR_GET_TYPE(vop, enable, LINE_FLAG_INTR);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+
+   return !!line_flag_irq;
+}
+
+static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
+{
+   unsigned long flags;
+
+   if (WARN_ON(!vop->is_enabled))
+   return;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   VOP_CTRL_SET(vop, line_flag_num[0], line_num);
+   VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+}
+
+static void vop_line_flag_irq_disable(struct vop *vop)
+{
+   unsigned long flags;
+
+   if (WARN_ON(!vop->is_enabled))
+   return;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   V

[PATCH v5 0/4] Add PSR function support for Analogix/Rockchip DP

2016-07-24 Thread Yakir Yang

The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make a lots
of sense to save the power consumption.

The v5 version have made the psr_set_state() to a delay work, which is
the biggest changes from v4.

The v3 version have splited an common PSR driver for Rockchip, which is
biggest changes from v2.

This thread is based on Mark's RK3399 VOP thread[0].

[0]: https://patchwork.kernel.org/patch/8886041/


Changes in v5:
- Add reviewed flag from Sean.
- Only keep 'psr_list_mutex' at register/unregister time.
- Remove unused global variables.
- Make list traversal safely at rockchip_drm_psr_unregister().
- Make psr_set_state() to a delay work, safe to call exported symbols at
  interrupt context.
- Remove the repeated psr delay work in vop driver.
- Add reviewed flag from Sean.
- Add reviewed flag from Sean.

Changes in v4.1:
- Remove the completion_done() check in irq handler (Sean)
- Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
- Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
- Add comment about PBx magic numbers. (Sean)

Changes in v4:
- Avoid the weird behavior in rockchip_drm_wait_line_flag(). (Sean)
- Make line_flag_num_x to an array. (Sean)
- Remove the unused vop_cfg_done() in vop_line_flag_irq_enable(). (Stephane, 
reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/349084/33/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 466]
- Tuck the global "psr_list" & "psr_list_mutex" in struct rockchip_drm_private. 
(Sean)
- Move the access of "psr->state" under "psr->state_mutex"'s protect. (Sean)
- Let "psr->state = PSR_FLUSH" under "psr->state_mutex"'s protect. (Sean)
- Collect psr_enable() and psr_disable() into psr_set_state()
- s/5\ second/PSR_FLUSH_TIMEOUT/ (Sean)
- Flush the psr callback in vop_crtc_disable(). (Stéphane, reviewed in Google 
gerrit)

[https://chromium-review.googlesource.com/#/c/349084/6/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 475]
- Add the missing file head with license. (Stéphane, reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/357563/1/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
 at 3]
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().
- Return 'void' instead of 'int' in analogix_dp_psr_set(). (Sean)
- Pull the 10ms delay time out into a #define. (Sean)
- Improved the code of analogix_dp_psr_work(). (Sean)
- Indented with spaces for new numbers in rockchip_dp_device struct. 
(Stéphane, reviewed at Google gerrit)

[https://chromium-review.googlesource.com/#/c/349085/33/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 83]

Changes in v3:
- Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
- Add 'line_flag_num_0' for RK3288/RK3036
- Remove the notify for waiting line_flag event (Daniel)
- split the psr flow into an common abstracted PSR driver
- implement the 'fb->dirty' callback function (Daniel)
- avoid to use notify to acqiure for vact event (Daniel)
- remove psr_active() callback which introduce in v2
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments
- split the common psr logic into a seperate driver, make this to a
  simple sub-psr device driver.

Changes in v2:
- Introduce in v2, split VOP line flag changes out
- introduce in v2, splite the common Analogix DP changes out
- remove vblank notify out (Daniel)
- create a psr_active() callback in vop data struct.

Yakir Yang (4):
  drm/rockchip: vop: export line flag function
  drm/rockchip: add an common abstracted PSR driver
  drm/bridge: analogix_dp: add the PSR function support
  drm/rockchip: analogix_dp: implement PSR function

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  81 +++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |   5 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  |  51 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  |  34 +++
 drivers/gpu/drm/rockchip/Makefile  |   2 +-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c|  57 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c|   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h|   6 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c |  12 +
 drivers/gpu/drm/rockchip/rockchip_drm_psr.c| 249 ++

[PATCH v2 3/3] drm/bridge: analogix_dp: remove the panel prepare/unprepare in suspend/resume

2016-07-22 Thread Yakir Yang
We already manager the panel power status in bridge_disable and
connector->detect functions, then we don't need to manager the
panel power status at suspend/resume in particular.

Signed-off-by: Yakir Yang 
---
Changes in v2: None

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 0ddaf93..3dadad2 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1413,11 +1413,6 @@ int analogix_dp_suspend(struct device *dev)

clk_disable_unprepare(dp->clock);

-   if (dp->plat_data->panel) {
-   if (drm_panel_unprepare(dp->plat_data->panel))
-   DRM_ERROR("failed to turnoff the panel\n");
-   }
-
return 0;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_suspend);
@@ -1433,13 +1428,6 @@ int analogix_dp_resume(struct device *dev)
return ret;
}

-   if (dp->plat_data->panel) {
-   if (drm_panel_prepare(dp->plat_data->panel)) {
-   DRM_ERROR("failed to setup the panel\n");
-   return -EBUSY;
-   }
-   }
-
return 0;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_resume);
-- 
1.9.1




[PATCH v2 2/3] drm/bridge: analogix_dp: turn off the panel when eDP need to disable

2016-07-22 Thread Yakir Yang
Some panels (like Sharp LQ123P1JX31) need to be turn off when eDP
controller stop to send valid video signal, otherwhise panel would
go burn in, and keep flicker and flicker.

So it's better to turn off the panel when eDP need to disable, and
we need to turn on the panel in connector->detect() callback, so
that driver would detect panel status rightly.

Signed-off-by: Yakir Yang 
---
Changes in v2:
- s/Panle/Panel/ (Sean)
- Move the drm_panel_ out of a conditional, and throw the return
  code away (Sean)
- Add comments about why we need unprepare the panel in bridge_disable (Sean)
- Unprepare the panel at the end of bridge->disable() function.

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 37 --
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..0ddaf93 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -960,6 +960,17 @@ enum drm_connector_status
 analogix_dp_detect(struct drm_connector *connector, bool force)
 {
struct analogix_dp_device *dp = to_dp(connector);
+   int ret;
+
+   /*
+* Panel would prepare for several times here, but don't worry, it
+* would only enable the hardware at the first prepare time.
+*/
+   if (dp->plat_data->panel) {
+   ret = drm_panel_prepare(dp->plat_data->panel);
+   if (ret)
+   DRM_ERROR("failed to setup the panel ret = %d\n", ret);
+   }

if (analogix_dp_detect_hpd(dp))
return connector_status_disconnected;
@@ -1058,13 +1069,15 @@ static void analogix_dp_bridge_enable(struct drm_bridge 
*bridge)
 static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
 {
struct analogix_dp_device *dp = bridge->driver_private;
+   int ret;

if (dp->dpms_mode != DRM_MODE_DPMS_ON)
return;

if (dp->plat_data->panel) {
-   if (drm_panel_disable(dp->plat_data->panel)) {
-   DRM_ERROR("failed to disable the panel\n");
+   ret = drm_panel_disable(dp->plat_data->panel);
+   if (ret) {
+   DRM_ERROR("failed to disable the panel [%d]\n", ret);
return;
}
}
@@ -1077,6 +1090,19 @@ static void analogix_dp_bridge_disable(struct drm_bridge 
*bridge)

pm_runtime_put_sync(dp->dev);

+   /*
+* Some panels need to be turn off when eDP controller stop to send
+* valid video signal, otherwhise panel would go burn in, and keep
+* flicker and flicker.
+*/
+   if (dp->plat_data->panel) {
+ret = drm_panel_unprepare(dp->plat_data->panel);
+if (ret) {
+   DRM_ERROR("failed to turnoff the panel [%d]\n", ret);
+   return;
+   }
+   }
+
dp->dpms_mode = DRM_MODE_DPMS_OFF;
 }

@@ -1333,13 +1359,6 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,

phy_power_on(dp->phy);

-   if (dp->plat_data->panel) {
-   if (drm_panel_prepare(dp->plat_data->panel)) {
-   DRM_ERROR("failed to setup the panel\n");
-   return -EBUSY;
-   }
-   }
-
analogix_dp_init_dp(dp);

ret = devm_request_threaded_irq(>dev, dp->irq,
-- 
1.9.1




[PATCH v2 1/3] drm/panel: simple-panel: add the delay timing for Sharp LQ123P1JX31

2016-07-22 Thread Yakir Yang
According to page 16 of Sharp LQ123P1JX31 datasheet, we need to add the
missing delay timing. Panel prepare time should be t1 (0.5ms~10ms) plus
t3 (0ms~100ms), and panel enable time should equal to t7 (0ms~50ms), and
panel unprepare time should be t11 (1ms~50ms) plus t12 (500ms~).

Signed-off-by: Yakir Yang 
Reviewed-by: Sean Paul 
---
Changes in v2:
- Add the reviewed tag from Sean.

 drivers/gpu/drm/panel/panel-simple.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 85143d1..f178998 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1384,6 +1384,11 @@ static const struct panel_desc sharp_lq123p1jx31 = {
.width = 259,
.height = 173,
},
+   .delay = {
+   .prepare = 110,
+   .enable = 50,
+   .unprepare = 550,
+   },
 };

 static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = {
-- 
1.9.1




[PATCH v1 1/2] drm/panel: simple-panel: add the delay timing for Sharp LQ123P1JX31

2016-07-22 Thread Yakir Yang
Sean,

On 07/21/2016 10:30 PM, Sean Paul wrote:
> On Thu, Jul 21, 2016 at 9:14 AM, Yakir Yang  wrote:
>> According to page 16 of Sharp LQ123P1JX31 datasheet, we need to add the
>> missing delay timing. Panel prepare time should be t1 (0.5ms~10ms) plus
>> t3 (0ms~100ms), and panel enable time should equal to t7 (0ms~50ms), and
>> panel unprepare time should be t11 (1ms~50ms) plus t12 (500ms~).
>>
>> Signed-off-by: Yakir Yang 
> Reviewed-by: Sean Paul 

Thanks  :-D

- Yakir

>> ---
>>   drivers/gpu/drm/panel/panel-simple.c | 5 +
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/panel/panel-simple.c 
>> b/drivers/gpu/drm/panel/panel-simple.c
>> index 85143d1..f178998 100644
>> --- a/drivers/gpu/drm/panel/panel-simple.c
>> +++ b/drivers/gpu/drm/panel/panel-simple.c
>> @@ -1384,6 +1384,11 @@ static const struct panel_desc sharp_lq123p1jx31 = {
>>  .width = 259,
>>  .height = 173,
>>  },
>> +   .delay = {
>> +   .prepare = 110,
>> +   .enable = 50,
>> +   .unprepare = 550,
>> +   },
>>   };
>>
>>   static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = {
>> --
>> 1.9.1
>>
>>
>
>




[PATCH v1 2/2] drm/bridge: analogix_dp: turn off the panel when eDP need to disable

2016-07-22 Thread Yakir Yang
Sean,

Thanks for your fast respond :-)

But this patch is not the latest one, I have upgraded this to "v1.1" 
version to fix the eDP can't be disabled problem:
 [PATCH v1.1 2/2] drm/bridge: analogix_dp: turn off the panel when 
eDP need to disable
 Changes in v1.1: - unprepare the panel at the end of 
bridge->disable() function

In spite of this, I would take your comments with my "v1.1" patch.

On 07/21/2016 10:28 PM, Sean Paul wrote:
> On Thu, Jul 21, 2016 at 9:14 AM, Yakir Yang  wrote:
>> Some panels (like Sharp LQ123P1JX31) need to be turn off when eDP
>> controller stop to send valid video signal, otherwhise panel would
>> go burn in, and keep flicker and flicker.
>>
>> So it's better to turn off the panel when eDP need to disable, and
>> we need to turn on the panel in connector->detect() callback, so
>> that driver would detect panel status rightly.
>>
>> Signed-off-by: Yakir Yang 
>> ---
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 18 ++
>>   1 file changed, 10 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 32715da..ea059b3 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -961,6 +961,14 @@ analogix_dp_detect(struct drm_connector *connector, 
>> bool force)
>>   {
>>  struct analogix_dp_device *dp = to_dp(connector);
>>
>> +   /*
>> +* Panle would prepare for several times here, but don't worry it
> s/Panle/Panel/

Done

>> +* would only enable the hardware at the first prepare time.
>
> Errr, this shouldn't go in detect. How about putting this in
> bridge_enable instead?

Nope, if we put this in bridge_enable, then eDP would never be enabled. 
Here're the calling flow.

--> analogix_dp_probe
   --> analogix_dp_bind  # we still haven't prepared the panel here, 
that means panel have been powered up
 --> analogix_dp_detect  # Oops, losing panel valid hotplug signal, 
cause panel have been powered up
 --> ** Keep detecting **

>> +*/
>> +   if (dp->plat_data->panel)
>> +   if (drm_panel_prepare(dp->plat_data->panel))
> Personally, I don't like doing work in a conditional since you're
> throwing the return code away. Could you break this out into:
>
> ret = drm_panel_prepare(dp->plat_data->panel);
> if (ret)
>DRM_ERROR("failed to setup the panel ret=%d\n", ret);

Okay

>
>> +   DRM_ERROR("failed to setup the panel\n");
>> +
>>  if (analogix_dp_detect_hpd(dp))
>>  return connector_status_disconnected;
>>
>> @@ -1063,7 +1071,8 @@ static void analogix_dp_bridge_disable(struct 
>> drm_bridge *bridge)
>>  return;
>>
>>  if (dp->plat_data->panel) {
>> -   if (drm_panel_disable(dp->plat_data->panel)) {
>> +   if (drm_panel_disable(dp->plat_data->panel) ||
>> +   drm_panel_unprepare(dp->plat_data->panel)) {
> Same comment here, please break this out into separate statements for
> better readability/logging.

Okay,


Thanks,
- Yakir

>
>>  DRM_ERROR("failed to disable the panel\n");
>>  return;
>>  }
>> @@ -1333,13 +1342,6 @@ int analogix_dp_bind(struct device *dev, struct 
>> drm_device *drm_dev,
>>
>>  phy_power_on(dp->phy);
>>
>> -   if (dp->plat_data->panel) {
>> -   if (drm_panel_prepare(dp->plat_data->panel)) {
>> -   DRM_ERROR("failed to setup the panel\n");
>> -   return -EBUSY;
>> -   }
>> -   }
>> -
>>  analogix_dp_init_dp(dp);
>>
>>  ret = devm_request_threaded_irq(>dev, dp->irq,
>> --
>> 1.9.1
>>
>>
>
>

-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160722/5c4a6f5c/attachment.html>


[PATCH v1.1 2/2] drm/bridge: analogix_dp: turn off the panel when eDP need to disable

2016-07-21 Thread Yakir Yang
Some panels (like Sharp LQ123P1JX31) need to be turn off when eDP
controller stop to send valid video signal, otherwhise panel would
go burn in, and keep flicker and flicker.

So it's better to turn off the panel when eDP need to disable, and
we need to turn on the panel in connector->detect() callback, so
that driver would detect panel status rightly.

Signed-off-by: Yakir Yang 
---

Changes in v1.1:
- unprepare the panel at the end of bridge->disable() function

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 22 +++---
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..2e519bd 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -961,6 +961,14 @@ analogix_dp_detect(struct drm_connector *connector, bool 
force)
 {
struct analogix_dp_device *dp = to_dp(connector);

+   /*
+* Panle would prepare for several times here, but don't worry it
+* would only enable the hardware at the first prepare time.
+*/
+   if (dp->plat_data->panel)
+   if (drm_panel_prepare(dp->plat_data->panel))
+   DRM_ERROR("failed to setup the panel\n");
+
if (analogix_dp_detect_hpd(dp))
return connector_status_disconnected;

@@ -1077,6 +1085,13 @@ static void analogix_dp_bridge_disable(struct drm_bridge 
*bridge)

pm_runtime_put_sync(dp->dev);

+   if (dp->plat_data->panel) {
+   if (drm_panel_unprepare(dp->plat_data->panel)) {
+   DRM_ERROR("failed to turnoff the panel\n");
+   return;
+   }
+   }
+
dp->dpms_mode = DRM_MODE_DPMS_OFF;
 }

@@ -1333,13 +1348,6 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,

phy_power_on(dp->phy);

-   if (dp->plat_data->panel) {
-   if (drm_panel_prepare(dp->plat_data->panel)) {
-   DRM_ERROR("failed to setup the panel\n");
-   return -EBUSY;
-   }
-   }
-
analogix_dp_init_dp(dp);

ret = devm_request_threaded_irq(>dev, dp->irq,
-- 
1.9.1




[PATCH v1 2/2] drm/bridge: analogix_dp: turn off the panel when eDP need to disable

2016-07-21 Thread Yakir Yang
Some panels (like Sharp LQ123P1JX31) need to be turn off when eDP
controller stop to send valid video signal, otherwhise panel would
go burn in, and keep flicker and flicker.

So it's better to turn off the panel when eDP need to disable, and
we need to turn on the panel in connector->detect() callback, so
that driver would detect panel status rightly.

Signed-off-by: Yakir Yang 
---
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..ea059b3 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -961,6 +961,14 @@ analogix_dp_detect(struct drm_connector *connector, bool 
force)
 {
struct analogix_dp_device *dp = to_dp(connector);

+   /*
+* Panle would prepare for several times here, but don't worry it
+* would only enable the hardware at the first prepare time.
+*/
+   if (dp->plat_data->panel)
+   if (drm_panel_prepare(dp->plat_data->panel))
+   DRM_ERROR("failed to setup the panel\n");
+
if (analogix_dp_detect_hpd(dp))
return connector_status_disconnected;

@@ -1063,7 +1071,8 @@ static void analogix_dp_bridge_disable(struct drm_bridge 
*bridge)
return;

if (dp->plat_data->panel) {
-   if (drm_panel_disable(dp->plat_data->panel)) {
+   if (drm_panel_disable(dp->plat_data->panel) ||
+   drm_panel_unprepare(dp->plat_data->panel)) {
DRM_ERROR("failed to disable the panel\n");
return;
}
@@ -1333,13 +1342,6 @@ int analogix_dp_bind(struct device *dev, struct 
drm_device *drm_dev,

phy_power_on(dp->phy);

-   if (dp->plat_data->panel) {
-   if (drm_panel_prepare(dp->plat_data->panel)) {
-   DRM_ERROR("failed to setup the panel\n");
-   return -EBUSY;
-   }
-   }
-
analogix_dp_init_dp(dp);

ret = devm_request_threaded_irq(>dev, dp->irq,
-- 
1.9.1




[PATCH v1 1/2] drm/panel: simple-panel: add the delay timing for Sharp LQ123P1JX31

2016-07-21 Thread Yakir Yang
According to page 16 of Sharp LQ123P1JX31 datasheet, we need to add the
missing delay timing. Panel prepare time should be t1 (0.5ms~10ms) plus
t3 (0ms~100ms), and panel enable time should equal to t7 (0ms~50ms), and
panel unprepare time should be t11 (1ms~50ms) plus t12 (500ms~).

Signed-off-by: Yakir Yang 
---
 drivers/gpu/drm/panel/panel-simple.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 85143d1..f178998 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1384,6 +1384,11 @@ static const struct panel_desc sharp_lq123p1jx31 = {
.width = 259,
.height = 173,
},
+   .delay = {
+   .prepare = 110,
+   .enable = 50,
+   .unprepare = 550,
+   },
 };

 static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = {
-- 
1.9.1




[PATCH v3 1/6] dt-bindings: add LG LP097QX1-SPA1 panel binding

2016-07-19 Thread Yakir Yang
Thierry,

On 07/08/2016 05:57 AM, Thierry Reding wrote:
> On Thu, Jul 07, 2016 at 11:55:23PM +0200, Thierry Reding wrote:
>> On Sun, Jun 12, 2016 at 10:53:30AM +0800, Yakir Yang wrote:
>>> The LG LP097QX1-SPA1 is an 9.7", 2048x1536 (QXGA) TFT-LCD panel
>>> connected using eDP interfaces.
>>>
>>> Signed-off-by: Yakir Yang 
>>> Acked-by: Rob Herring 
>>> ---
>>> Changes in v3: None
>>> Changes in v2:
>>> - Add Rob's acked for dt-bindings of LG LP097QX1-SPA1 panel
>>>
>>>   .../devicetree/bindings/display/panel/lg,lp097qx1-spa1.txt | 7 
>>> +++
>>>   1 file changed, 7 insertions(+)
>>>   create mode 100644 
>>> Documentation/devicetree/bindings/display/panel/lg,lp097qx1-spa1.txt
>> Applied all six patches, though I modified 3/6 as Doug suggested.
> I mean patch 4/6, of course.

Wow, good news, thanks a lot :-D

- Yakir

> Thierry




[PATCH v4.1 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-16 Thread Yakir Yang
Sean,

On 07/15/2016 09:13 PM, Sean Paul wrote:
> On Fri, Jul 15, 2016 at 06:55:17PM +0800, Yakir Yang wrote:
>> The full name of PSR is Panel Self Refresh, panel device could refresh
>> itself with the hardware framebuffer in panel, this would make lots of
>> sense to save the power consumption.
>>
>> This patch have exported two symbols for platform driver to implement
>> the PSR function in hardware side:
>> - analogix_dp_active_psr()
>> - analogix_dp_inactive_psr()
>>
>> Signed-off-by: Yakir Yang 
> Reviewed-by: Sean Paul 

Thanks for your reviewed  :-D

- Yakir

>
>> ---
>> Changes in v4.1:
>> - Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
>> - Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
>> - Add comment about PBx magic numbers. (Sean)
>>
>> Changes in v4:
>> - Downgrade the PSR version print message to debug level. (Sean)
>> - Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
>> - Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
>> (Sean)
>> - Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
>> - Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
>> - Rename "active/inactive" to "enable/disable". (Sean, Dominik)
>> - Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().
>>
>> Changes in v3:
>> - split analogix_dp_enable_psr(), make it more clearly
>>  analogix_dp_detect_sink_psr()
>>  analogix_dp_enable_sink_psr()
>> - remove some nosie register setting comments
>>
>> Changes in v2:
>> - introduce in v2, splite the common Analogix DP changes out
>>
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 
>> ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
>>   include/drm/bridge/analogix_dp.h   |  3 +
>>   5 files changed, 174 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 32715da..381b25e 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct 
>> analogix_dp_device *dp)
>>  return 0;
>>   }
>>   
>> +int analogix_dp_enable_psr(struct device *dev)
>> +{
>> +struct analogix_dp_device *dp = dev_get_drvdata(dev);
>> +struct edp_vsc_psr psr_vsc;
>> +
>> +if (!dp->psr_support)
>> +return -EINVAL;
>> +
>> +/* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
>> +memset(_vsc, 0, sizeof(psr_vsc));
>> +psr_vsc.sdp_header.HB0 = 0;
>> +psr_vsc.sdp_header.HB1 = 0x7;
>> +psr_vsc.sdp_header.HB2 = 0x2;
>> +psr_vsc.sdp_header.HB3 = 0x8;
>> +
>> +psr_vsc.DB0 = 0;
>> +psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
>> +
>> +analogix_dp_send_psr_spd(dp, _vsc);
>> +return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
>> +
>> +int analogix_dp_disable_psr(struct device *dev)
>> +{
>> +struct analogix_dp_device *dp = dev_get_drvdata(dev);
>> +struct edp_vsc_psr psr_vsc;
>> +
>> +if (!dp->psr_support)
>> +return -EINVAL;
>> +
>> +/* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
>> +memset(_vsc, 0, sizeof(psr_vsc));
>> +psr_vsc.sdp_header.HB0 = 0;
>> +psr_vsc.sdp_header.HB1 = 0x7;
>> +psr_vsc.sdp_header.HB2 = 0x2;
>> +psr_vsc.sdp_header.HB3 = 0x8;
>> +
>> +psr_vsc.DB0 = 0;
>> +psr_vsc.DB1 = 0;
>> +
>> +analogix_dp_send_psr_spd(dp, _vsc);
>> +return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
>> +
>> +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
>> +{
>> +unsigned char psr_version;
>> +
>> +analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
>> +dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
>> +
>> +return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
>> +}
>> +
>> +static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
>> +{
>> +unsigned

[PATCH v4.1 1/4] drm/rockchip: vop: export line flag function

2016-07-16 Thread Yakir Yang
Sean,

On 07/15/2016 09:04 PM, Sean Paul wrote:
> On Fri, Jul 15, 2016 at 6:55 AM, Yakir Yang  wrote:
>> VOP have integrated a hardware counter which indicate the exact display
>> line that vop is scanning. And if we're interested in a specific line,
>> we can set the line number to vop line_flag register, and then vop would
>> generate a line_flag interrupt for it.
>>
>> For example eDP PSR function is interested in the vertical blanking
>> period, then driver could set the line number to zero.
>>
>> This patch have exported a symbol that allow other driver to listen the
>> line flag event with given timeout limit:
>> -  rockchip_drm_wait_line_flag()
>>
>> Signed-off-by: Yakir Yang 
>
> Thanks for the update.
>
> Reviewed-by: Sean Paul 

Thanks for your reviewed  :-D

- Yakir

>> ---
>> Changes in v4.1:
>> - Remove the completion_done() check in irq handler (Sean)
>>
>> Changes in v4:
>> - Avoid the weird behavior in rockchip_drm_wait_line_flag(). (Sean)
>> - Make line_flag_num_x to an array. (Sean)
>> - Remove the unused vop_cfg_done() in vop_line_flag_irq_enable(). (Stephane, 
>> reviewed in Google gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/349084/33/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>  at 466]
>>
>> Changes in v3:
>> - Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
>> - Add 'line_flag_num_0' for RK3288/RK3036
>> - Remove the notify for waiting line_flag event (Daniel)
>>
>> Changes in v2:
>> - Introduce in v2, split VOP line flag changes out
>>
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 117 
>> 
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   2 +
>>   drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   4 +
>>   4 files changed, 126 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
>> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> index ea39329..239b830 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> @@ -70,4 +70,7 @@ int rockchip_drm_dma_attach_device(struct drm_device 
>> *drm_dev,
>> struct device *dev);
>>   void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
>>  struct device *dev);
>> +int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int 
>> line_num,
>> +   unsigned int mstimeout);
>> +
>>   #endif /* _ROCKCHIP_DRM_DRV_H_ */
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> index c8a62a8..8a4f36e 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -121,6 +121,8 @@ struct vop {
>>  /* protected by dev->event_lock */
>>  struct drm_pending_vblank_event *event;
>>
>> +   struct completion line_flag_completion;
>> +
>>  const struct vop_data *data;
>>
>>  uint32_t *regsbak;
>> @@ -431,6 +433,71 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
>> *vop)
>>  spin_unlock_irqrestore(>irq_lock, flags);
>>   }
>>
>> +/*
>> + * (1) each frame starts at the start of the Vsync pulse which is signaled 
>> by
>> + * the "FRAME_SYNC" interrupt.
>> + * (2) the active data region of each frame ends at dsp_vact_end
>> + * (3) we should program this same number (dsp_vact_end) into 
>> dsp_line_frag_num,
>> + *  to get "LINE_FLAG" interrupt at the end of the active on screen 
>> data.
>> + *
>> + * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
>> + * Interrupts
>> + * LINE_FLAG ---+
>> + * FRAME_SYNC + |
>> + *| |
>> + *v v
>> + *| Vsync | Vbp |  Vactive  | Vfp |
>> + *^ ^   ^ ^
>> + *| |   | |
>> + *| |   | |
>> + * dsp_vs_end + |   | |   VOP_DSP_VTOTAL_VS_END
>> + * dsp_vact_start --+   | |   VOP_DSP_VACT_ST_END
>> + * dsp_vact_end + |   VOP_DSP_VACT_ST_END
>> + * dsp_t

[PATCH v4.1 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Yakir Yang
The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Signed-off-by: Yakir Yang 
---
Changes in v4.1:
- Take use of existing edp_psr_vsc struct to swap HBx and DBx setting. (Sean)
- Remove PSR_VID_CRC_FLUSH setting analogix_dp_enable_psr_crc().
- Add comment about PBx magic numbers. (Sean)

Changes in v4:
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().

Changes in v3:
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments

Changes in v2:
- introduce in v2, splite the common Analogix DP changes out

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 81 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  5 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 51 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 34 +
 include/drm/bridge/analogix_dp.h   |  3 +
 5 files changed, 174 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..381b25e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,83 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }

+int analogix_dp_enable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
+
+int analogix_dp_disable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+   struct edp_vsc_psr psr_vsc;
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
+   memset(_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+
+   psr_vsc.DB0 = 0;
+   psr_vsc.DB1 = 0;
+
+   analogix_dp_send_psr_spd(dp, _vsc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
+
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_version;
+
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
+   dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
+
+   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
+}
+
+static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_en;
+
+   /* Disable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en &= ~DP_PSR_ENABLE;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Main-Link transmitter remains active during PSR active states */
+   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Enable psr function */
+   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
+DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   analogix_dp_enable_psr_crc(dp);
+}
+
 static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
 {
int i;
@@ -921,6 +998,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
*dp)

/* Enable video */
analogix_dp_start_video(dp);
+
+   dp->psr_support = analogix_dp_detect_sink_psr(dp);
+   if (dp->psr_support)
+   analogix_dp_enable_sink_psr(dp);
 }

 int analogix_dp_get_modes(

[PATCH v4.1 1/4] drm/rockchip: vop: export line flag function

2016-07-15 Thread Yakir Yang
VOP have integrated a hardware counter which indicate the exact display
line that vop is scanning. And if we're interested in a specific line,
we can set the line number to vop line_flag register, and then vop would
generate a line_flag interrupt for it.

For example eDP PSR function is interested in the vertical blanking
period, then driver could set the line number to zero.

This patch have exported a symbol that allow other driver to listen the
line flag event with given timeout limit:
-  rockchip_drm_wait_line_flag()

Signed-off-by: Yakir Yang 
---
Changes in v4.1:
- Remove the completion_done() check in irq handler (Sean)

Changes in v4:
- Avoid the weird behavior in rockchip_drm_wait_line_flag(). (Sean)
- Make line_flag_num_x to an array. (Sean)
- Remove the unused vop_cfg_done() in vop_line_flag_irq_enable(). (Stephane, 
reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/349084/33/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 466]

Changes in v3:
- Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
- Add 'line_flag_num_0' for RK3288/RK3036
- Remove the notify for waiting line_flag event (Daniel)

Changes in v2:
- Introduce in v2, split VOP line flag changes out

 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 117 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   2 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   4 +
 4 files changed, 126 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..239b830 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -70,4 +70,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
+int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
+   unsigned int mstimeout);
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index c8a62a8..8a4f36e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -121,6 +121,8 @@ struct vop {
/* protected by dev->event_lock */
struct drm_pending_vblank_event *event;

+   struct completion line_flag_completion;
+
const struct vop_data *data;

uint32_t *regsbak;
@@ -431,6 +433,71 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+/*
+ * (1) each frame starts at the start of the Vsync pulse which is signaled by
+ * the "FRAME_SYNC" interrupt.
+ * (2) the active data region of each frame ends at dsp_vact_end
+ * (3) we should program this same number (dsp_vact_end) into 
dsp_line_frag_num,
+ *  to get "LINE_FLAG" interrupt at the end of the active on screen data.
+ *
+ * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
+ * Interrupts
+ * LINE_FLAG ---+
+ * FRAME_SYNC + |
+ *| |
+ *v v
+ *| Vsync | Vbp |  Vactive  | Vfp |
+ *^ ^   ^ ^
+ *| |   | |
+ *| |   | |
+ * dsp_vs_end + |   | |   VOP_DSP_VTOTAL_VS_END
+ * dsp_vact_start --+   | |   VOP_DSP_VACT_ST_END
+ * dsp_vact_end + |   VOP_DSP_VACT_ST_END
+ * dsp_total -+   VOP_DSP_VTOTAL_VS_END
+ */
+static bool vop_line_flag_irq_is_enabled(struct vop *vop)
+{
+   uint32_t line_flag_irq;
+   unsigned long flags;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   line_flag_irq = VOP_INTR_GET_TYPE(vop, enable, LINE_FLAG_INTR);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+
+   return !!line_flag_irq;
+}
+
+static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
+{
+   unsigned long flags;
+
+   if (WARN_ON(!vop->is_enabled))
+   return;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   VOP_CTRL_SET(vop, line_flag_num[0], line_num);
+   VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+}
+
+static void vop_line_flag_irq_disable(struct vop *vop)
+{
+   unsigned long flags;
+
+   if (WARN_ON(!vop->is_enabled))
+   return;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 0);
+
+   spin_unlock_irqrestore(

[PATCH v4 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Yakir Yang
Sean,

On 07/15/2016 05:32 PM, Yakir Yang wrote:
> Sean,
>
> On 07/14/2016 11:23 PM, Sean Paul wrote:
>> On Thu, Jul 14, 2016 at 12:15:53PM +0800, Yakir Yang wrote:
>>> The full name of PSR is Panel Self Refresh, panel device could refresh
>>> itself with the hardware framebuffer in panel, this would make lots of
>>> sense to save the power consumption.
>>>
>>> This patch have exported two symbols for platform driver to implement
>>> the PSR function in hardware side:
>>> - analogix_dp_active_psr()
>>> - analogix_dp_inactive_psr()
>>>
>>> Signed-off-by: Yakir Yang
>>> ---
>>> Changes in v4:
>>> - Downgrade the PSR version print message to debug level. (Sean)
>>> - Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
>>> - Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
>>> (Sean)
>>> - Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
>>> - Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
>>> - Rename "active/inactive" to "enable/disable". (Sean, Dominik)
>>> - Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().
>>>
>>> Changes in v3:
>>> - split analogix_dp_enable_psr(), make it more clearly
>>>  analogix_dp_detect_sink_psr()
>>>  analogix_dp_enable_sink_psr()
>>> - remove some nosie register setting comments
>>>
>>> Changes in v2:
>>> - introduce in v2, splite the common Analogix DP changes out
>>>
>>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 60 
>>> ++
>>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++
>>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 49 ++
>>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 28 ++
>>>   include/drm/bridge/analogix_dp.h   |  3 ++
>>>   5 files changed, 144 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>> index 32715da..1fec91a 100644
>>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>> @@ -97,6 +97,62 @@ static int analogix_dp_detect_hpd(struct 
>>> analogix_dp_device *dp)
>>> return 0;
>>>   }
>>>   
>>> +int analogix_dp_enable_psr(struct device *dev)
>>> +{
>>> +   struct analogix_dp_device *dp = dev_get_drvdata(dev);
>>> +
>>> +   if (!dp->psr_support)
>>> +   return -EINVAL;
>>> +
>>> +   analogix_dp_send_psr_spd(dp, EDP_VSC_PSR_STATE_ACTIVE |
>>> +EDP_VSC_PSR_CRC_VALUES_VALID);
>>> +   return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
>>> +
>>> +int analogix_dp_disable_psr(struct device *dev)
>>> +{
>>> +   struct analogix_dp_device *dp = dev_get_drvdata(dev);
>>> +
>>> +   if (!dp->psr_support)
>>> +   return -EINVAL;
>>> +
>>> +   analogix_dp_send_psr_spd(dp, 0);
>>> +   return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
>>> +
>>> +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
>>> +{
>>> +   unsigned char psr_version;
>>> +
>>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
>>> +   dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
>>> +
>>> +   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
>>> +}
>>> +
>>> +static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
>>> +{
>>> +   unsigned char psr_en;
>>> +
>>> +   /* Disable psr function */
>>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
>>> +   psr_en &= ~DP_PSR_ENABLE;
>>> +   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>>> +
>>> +   /* Main-Link transmitter remains active during PSR active states */
>>> +   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
>>> +   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>>> +
>>> +   /* Enable psr function */
>>> +   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
>>> +DP_PSR_CRC_VERIFICATION;
>>> +   

[PATCH v4 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-15 Thread Yakir Yang
Sean,

On 07/14/2016 11:23 PM, Sean Paul wrote:
> On Thu, Jul 14, 2016 at 12:15:53PM +0800, Yakir Yang wrote:
>> The full name of PSR is Panel Self Refresh, panel device could refresh
>> itself with the hardware framebuffer in panel, this would make lots of
>> sense to save the power consumption.
>>
>> This patch have exported two symbols for platform driver to implement
>> the PSR function in hardware side:
>> - analogix_dp_active_psr()
>> - analogix_dp_inactive_psr()
>>
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v4:
>> - Downgrade the PSR version print message to debug level. (Sean)
>> - Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
>> - Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
>> (Sean)
>> - Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
>> - Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
>> - Rename "active/inactive" to "enable/disable". (Sean, Dominik)
>> - Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().
>>
>> Changes in v3:
>> - split analogix_dp_enable_psr(), make it more clearly
>>  analogix_dp_detect_sink_psr()
>>  analogix_dp_enable_sink_psr()
>> - remove some nosie register setting comments
>>
>> Changes in v2:
>> - introduce in v2, splite the common Analogix DP changes out
>>
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 60 
>> ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 49 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 28 ++
>>   include/drm/bridge/analogix_dp.h   |  3 ++
>>   5 files changed, 144 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 32715da..1fec91a 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -97,6 +97,62 @@ static int analogix_dp_detect_hpd(struct 
>> analogix_dp_device *dp)
>>  return 0;
>>   }
>>   
>> +int analogix_dp_enable_psr(struct device *dev)
>> +{
>> +struct analogix_dp_device *dp = dev_get_drvdata(dev);
>> +
>> +if (!dp->psr_support)
>> +return -EINVAL;
>> +
>> +analogix_dp_send_psr_spd(dp, EDP_VSC_PSR_STATE_ACTIVE |
>> + EDP_VSC_PSR_CRC_VALUES_VALID);
>> +return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
>> +
>> +int analogix_dp_disable_psr(struct device *dev)
>> +{
>> +struct analogix_dp_device *dp = dev_get_drvdata(dev);
>> +
>> +if (!dp->psr_support)
>> +return -EINVAL;
>> +
>> +analogix_dp_send_psr_spd(dp, 0);
>> +return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
>> +
>> +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
>> +{
>> +unsigned char psr_version;
>> +
>> +analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
>> +dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
>> +
>> +return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
>> +}
>> +
>> +static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
>> +{
>> +unsigned char psr_en;
>> +
>> +/* Disable psr function */
>> +analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
>> +psr_en &= ~DP_PSR_ENABLE;
>> +analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>> +
>> +/* Main-Link transmitter remains active during PSR active states */
>> +psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
>> +analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>> +
>> +/* Enable psr function */
>> +psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
>> + DP_PSR_CRC_VERIFICATION;
>> +analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>> +
>> +analogix_dp_enable_psr_crc(dp);
>> +}
>> +
>>   static unsigned char analogix_dp_calc_edid_check_sum(unsigned char 
>> *edid_data)
>>   {
>>  int i;
>> @@ -921,6 +977,10 @@ static void analogix_dp_commit(struct 
>> analogix_dp_device *dp)
>>   
>>  /* Enable video */
>>  analog

[PATCH v4 4/4] drm/rockchip: analogix_dp: implement PSR function

2016-07-15 Thread Yakir Yang
Sean,

On 07/14/2016 11:26 PM, Sean Paul wrote:
> On Thu, Jul 14, 2016 at 12:15:58PM +0800, Yakir Yang wrote:
>> Alway enable the PSR function for Rockchip analogix_dp driver. If panel
>> don't support PSR, then the core analogix_dp would ignore this setting.
>>
>> Signed-off-by: Yakir Yang 
> Reviewed-by: Sean Paul 

Thanks :-D

- Yakir

>> ---
>> Changes in v4:
>> - Return 'void' instead of 'int' in analogix_dp_psr_set(). (Sean)
>> - Pull the 10ms delay time out into a #define. (Sean)
>> - Improved the code of analogix_dp_psr_work(). (Sean)
>> - Indented with spaces for new numbers in rockchip_dp_device struct. 
>> (Stéphane, reviewed at Google gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/349085/33/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>>  at 83]
>>
>> Changes in v3:
>> - split the common psr logic into a seperate driver, make this to a
>>simple sub-psr device driver.
>>
>> Changes in v2:
>> - remove vblank notify out (Daniel)
>> - create a psr_active() callback in vop data struct.
>>
>>   drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 57 
>> +
>>   1 file changed, 57 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
>> b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> index e81e19a..aa916f4 100644
>> --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> @@ -32,6 +32,7 @@
>>   #include 
>>   
>>   #include "rockchip_drm_drv.h"
>> +#include "rockchip_drm_psr.h"
>>   #include "rockchip_drm_vop.h"
>>   
>>   #define RK3288_GRF_SOC_CON60x25c
>> @@ -41,6 +42,9 @@
>>   
>>   #define HIWORD_UPDATE(val, mask)   (val | (mask) << 16)
>>   
>> +#define PSR_SET_DELAY_TIME  msecs_to_jiffies(10)
>> +#define PSR_WAIT_LINE_FLAG_TIMEOUT_MS   100
>> +
>>   #define to_dp(nm)  container_of(nm, struct rockchip_dp_device, nm)
>>   
>>   /**
>> @@ -68,11 +72,55 @@ struct rockchip_dp_device {
>>  struct regmap*grf;
>>  struct reset_control *rst;
>>   
>> +struct delayed_work  psr_work;
>> +unsigned int psr_state;
>> +
>>  const struct rockchip_dp_chip_data *data;
>>   
>>  struct analogix_dp_plat_data plat_data;
>>   };
>>   
>> +static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
>> +{
>> +struct rockchip_dp_device *dp = to_dp(encoder);
>> +
>> +dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
>> +
>> +if (enabled)
>> +dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
>> +else
>> +dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
>> +
>> +schedule_delayed_work(>psr_work, PSR_SET_DELAY_TIME);
>> +}
>> +
>> +static void analogix_dp_psr_work(struct work_struct *work)
>> +{
>> +struct rockchip_dp_device *dp =
>> +container_of(work, typeof(*dp), psr_work.work);
>> +struct drm_crtc *crtc = dp->encoder.crtc;
>> +int psr_state = dp->psr_state;
>> +int vact_end;
>> +int ret;
>> +
>> +if (!crtc)
>> +return;
>> +
>> +vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
>> crtc->mode.vdisplay;
>> +
>> +ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
>> +  PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
>> +if (ret) {
>> +dev_err(dp->dev, "line flag interrupt did not arrive\n");
>> +return;
>> +}
>> +
>> +if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
>> +analogix_dp_enable_psr(dp->dev);
>> +else
>> +analogix_dp_disable_psr(dp->dev);
>> +}
>> +
>>   static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
>>   {
>>  reset_control_assert(dp->rst);
>> @@ -340,12 +388,21 @@ static int rockchip_dp_bind(struct device *dev, struct 
>> device *master,
>>  dp->plat_data.power_off = rockchip_dp_powerdown;
>>  dp->plat_data.get_modes = rockchip_dp_get_modes;
>>   
>> +dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
>> +INIT_DELAYED_WORK(>psr_work, analogix_dp_psr_work);
>> +
>> +rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
>> +
>>  return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
>>   }
>>   
>>   static void rockchip_dp_unbind(struct device *dev, struct device *master,
>> void *data)
>>   {
>> +struct rockchip_dp_device *dp = dev_get_drvdata(dev);
>> +
>> +rockchip_drm_psr_unregister(>encoder);
>> +
>>  return analogix_dp_unbind(dev, master, data);
>>   }
>>   
>> -- 
>> 1.9.1
>>
>>
>> ___
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
>




[PATCH v4 2/4] drm/rockchip: add an common abstracted PSR driver

2016-07-15 Thread Yakir Yang
Sean,

On 07/14/2016 11:14 PM, Sean Paul wrote:
> On Thu, Jul 14, 2016 at 12:15:49PM +0800, Yakir Yang wrote:
>> The PSR driver have exported four symbols for specific device driver:
>> - rockchip_drm_psr_register()
>> - rockchip_drm_psr_unregister()
>> - rockchip_drm_psr_enable()
>> - rockchip_drm_psr_disable()
>> - rockchip_drm_psr_flush()
>>
>> Encoder driver should call the register/unregister interfaces to hook
>> itself into common PSR driver, encoder have implement the 'psr_set'
>> callback which use the set PSR state in hardware side.
>>
>> Crtc driver would call the enable/disable interfaces when vblank is
>> enable/disable, after that the common PSR driver would call the encoder
>> registered callback to set the PSR state.
>>
>> Fb driver would call the flush interface in 'fb->dirty' callback, this
>> helper function would force all PSR enabled encoders to exit from PSR
>> for 3 seconds.
>>
>> Signed-off-by: Yakir Yang 
>
> I still don't think it's a good idea to pull this out into a separate PSR
> driver, but I suppose we can integrate it at a later time if it becomes
> cumbersome.
>
> Reviewed-by: Sean Paul 

Thanks :-D

- Yakir

>
>> ---
>> Changes in v4:
>> - Tuck the global "psr_list" & "psr_list_mutex" in struct 
>> rockchip_drm_private. (Sean)
>> - Move the access of "psr->state" under "psr->state_mutex"'s protect. (Sean)
>> - Let "psr->state = PSR_FLUSH" under "psr->state_mutex"'s protect. (Sean)
>> - Collect psr_enable() and psr_disable() into psr_set_state()
>> - s/5\ second/PSR_FLUSH_TIMEOUT/ (Sean)
>> - Flush the psr callback in vop_crtc_disable(). (Stéphane, reviewed in 
>> Google gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/349084/6/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>  at 475]
>> - Add the missing file head with license. (Stéphane, reviewed in Google 
>> gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/357563/1/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
>>  at 3]
>>
>> Changes in v3:
>> - split the psr flow into an common abstracted PSR driver
>> - implement the 'fb->dirty' callback function (Daniel)
>> - avoid to use notify to acqiure for vact event (Daniel)
>> - remove psr_active() callback which introduce in v2
>>
>> Changes in v2: None
>>
>>   drivers/gpu/drm/rockchip/Makefile   |   2 +-
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   4 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  12 ++
>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 223 
>> 
>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  26 
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  29 
>>   7 files changed, 298 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h
>>
>> diff --git a/drivers/gpu/drm/rockchip/Makefile 
>> b/drivers/gpu/drm/rockchip/Makefile
>> index 05d0713..9746365 100644
>> --- a/drivers/gpu/drm/rockchip/Makefile
>> +++ b/drivers/gpu/drm/rockchip/Makefile
>> @@ -3,7 +3,7 @@
>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>   
>>   rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
>> -rockchip_drm_gem.o rockchip_drm_vop.o
>> +rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
>>   rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>>   
>>   obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
>> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> index d665fb0..26c12b3 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
>> @@ -156,6 +156,9 @@ static int rockchip_drm_bind(struct device *dev)
>>   
>>  drm_dev->dev_private = private;
>>   
>> +INIT_LIST_HEAD(>psr_list);
>> +mutex_init(>psr_list_mutex);
>> +
>>  drm_mode_config_init(drm_dev);
>>   
>>  rockchip_drm_mode_config_init(drm_dev);
>> @@ -218,6 +221,7 @@ static int rockchip_drm_bind(struct device *dev)
>>   
>>  if (is_support_iommu)
>>  arm_iommu_release_mapping(mapping);
>> +
>>  return 0;
>>   err_fbdev_fini:
>>  rockchip_drm_fbdev_fi

[PATCH v4 1/4] drm/rockchip: vop: export line flag function

2016-07-15 Thread Yakir Yang
Sean,

On 07/14/2016 10:46 PM, Sean Paul wrote:
> On Thu, Jul 14, 2016 at 12:15:44PM +0800, Yakir Yang wrote:
>> VOP have integrated a hardware counter which indicate the exact display
>> line that vop is scanning. And if we're interested in a specific line,
>> we can set the line number to vop line_flag register, and then vop would
>> generate a line_flag interrupt for it.
>>
>> For example eDP PSR function is interested in the vertical blanking
>> period, then driver could set the line number to zero.
>>
>> This patch have exported a symbol that allow other driver to listen the
>> line flag event with given timeout limit:
>> -  rockchip_drm_wait_line_flag()
>>
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v4:
>> - Avoid the weird behavior in rockchip_drm_wait_line_flag(). (Sean)
>> - Make line_flag_num_x to an array. (Sean)
>> - Remove the unused vop_cfg_done() in vop_line_flag_irq_enable(). (Stephane, 
>> reviewed in Google gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/349084/33/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>  at 466]
>>
>> Changes in v3:
>> - Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
>> - Add 'line_flag_num_0' for RK3288/RK3036
>> - Remove the notify for waiting line_flag event (Daniel)
>>
>> Changes in v2:
>> - Introduce in v2, split VOP line flag changes out
>>
>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 118 
>> 
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   2 +
>>   drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   4 +
>>   4 files changed, 127 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
>> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> index ea39329..239b830 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>> @@ -70,4 +70,7 @@ int rockchip_drm_dma_attach_device(struct drm_device 
>> *drm_dev,
>> struct device *dev);
>>   void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
>>  struct device *dev);
>> +int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int 
>> line_num,
>> +unsigned int mstimeout);
>> +
>>   #endif /* _ROCKCHIP_DRM_DRV_H_ */
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> index c8a62a8..69d32f1 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -121,6 +121,8 @@ struct vop {
>>  /* protected by dev->event_lock */
>>  struct drm_pending_vblank_event *event;
>>   
>> +struct completion line_flag_completion;
>> +
>>  const struct vop_data *data;
>>   
>>  uint32_t *regsbak;
>> @@ -431,6 +433,71 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
>> *vop)
>>  spin_unlock_irqrestore(>irq_lock, flags);
>>   }
>>   
>> +/*
>> + * (1) each frame starts at the start of the Vsync pulse which is signaled 
>> by
>> + * the "FRAME_SYNC" interrupt.
>> + * (2) the active data region of each frame ends at dsp_vact_end
>> + * (3) we should program this same number (dsp_vact_end) into 
>> dsp_line_frag_num,
>> + *  to get "LINE_FLAG" interrupt at the end of the active on screen 
>> data.
>> + *
>> + * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
>> + * Interrupts
>> + * LINE_FLAG ---+
>> + * FRAME_SYNC + |
>> + *| |
>> + *v v
>> + *| Vsync | Vbp |  Vactive  | Vfp |
>> + *^ ^   ^ ^
>> + *| |   | |
>> + *| |   | |
>> + * dsp_vs_end + |   | |   VOP_DSP_VTOTAL_VS_END
>> + * dsp_vact_start --+   | |   VOP_DSP_VACT_ST_END
>> + * dsp_vact_end + |   VOP_DSP_VACT_ST_END
>> + * dsp_total -+   VOP_DSP_VTOTAL_VS_END
>> + */
>> +static bool vop_line_flag_irq_is_enabled(struct vop *vop)
>> +{
>> +uint32_t line_flag_irq;
>> +unsigned lon

[PATCH v4 4/4] drm/rockchip: analogix_dp: implement PSR function

2016-07-14 Thread Yakir Yang
Alway enable the PSR function for Rockchip analogix_dp driver. If panel
don't support PSR, then the core analogix_dp would ignore this setting.

Signed-off-by: Yakir Yang 
---
Changes in v4:
- Return 'void' instead of 'int' in analogix_dp_psr_set(). (Sean)
- Pull the 10ms delay time out into a #define. (Sean)
- Improved the code of analogix_dp_psr_work(). (Sean)
- Indented with spaces for new numbers in rockchip_dp_device struct. 
(Stéphane, reviewed at Google gerrit)

[https://chromium-review.googlesource.com/#/c/349085/33/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 83]

Changes in v3:
- split the common psr logic into a seperate driver, make this to a
  simple sub-psr device driver.

Changes in v2:
- remove vblank notify out (Daniel)
- create a psr_active() callback in vop data struct.

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 57 +
 1 file changed, 57 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index e81e19a..aa916f4 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -32,6 +32,7 @@
 #include 

 #include "rockchip_drm_drv.h"
+#include "rockchip_drm_psr.h"
 #include "rockchip_drm_vop.h"

 #define RK3288_GRF_SOC_CON60x25c
@@ -41,6 +42,9 @@

 #define HIWORD_UPDATE(val, mask)   (val | (mask) << 16)

+#define PSR_SET_DELAY_TIME msecs_to_jiffies(10)
+#define PSR_WAIT_LINE_FLAG_TIMEOUT_MS  100
+
 #define to_dp(nm)  container_of(nm, struct rockchip_dp_device, nm)

 /**
@@ -68,11 +72,55 @@ struct rockchip_dp_device {
struct regmap*grf;
struct reset_control *rst;

+   struct delayed_work  psr_work;
+   unsigned int psr_state;
+
const struct rockchip_dp_chip_data *data;

struct analogix_dp_plat_data plat_data;
 };

+static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
+{
+   struct rockchip_dp_device *dp = to_dp(encoder);
+
+   dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
+
+   if (enabled)
+   dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
+   else
+   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
+
+   schedule_delayed_work(>psr_work, PSR_SET_DELAY_TIME);
+}
+
+static void analogix_dp_psr_work(struct work_struct *work)
+{
+   struct rockchip_dp_device *dp =
+   container_of(work, typeof(*dp), psr_work.work);
+   struct drm_crtc *crtc = dp->encoder.crtc;
+   int psr_state = dp->psr_state;
+   int vact_end;
+   int ret;
+
+   if (!crtc)
+   return;
+
+   vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
crtc->mode.vdisplay;
+
+   ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end,
+ PSR_WAIT_LINE_FLAG_TIMEOUT_MS);
+   if (ret) {
+   dev_err(dp->dev, "line flag interrupt did not arrive\n");
+   return;
+   }
+
+   if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
+   analogix_dp_enable_psr(dp->dev);
+   else
+   analogix_dp_disable_psr(dp->dev);
+}
+
 static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
 {
reset_control_assert(dp->rst);
@@ -340,12 +388,21 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
dp->plat_data.power_off = rockchip_dp_powerdown;
dp->plat_data.get_modes = rockchip_dp_get_modes;

+   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
+   INIT_DELAYED_WORK(>psr_work, analogix_dp_psr_work);
+
+   rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
+
return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
 }

 static void rockchip_dp_unbind(struct device *dev, struct device *master,
   void *data)
 {
+   struct rockchip_dp_device *dp = dev_get_drvdata(dev);
+
+   rockchip_drm_psr_unregister(>encoder);
+
return analogix_dp_unbind(dev, master, data);
 }

-- 
1.9.1




[PATCH v4 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-14 Thread Yakir Yang
The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Signed-off-by: Yakir Yang 
---
Changes in v4:
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().

Changes in v3:
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments

Changes in v2:
- introduce in v2, splite the common Analogix DP changes out

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 60 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 49 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 28 ++
 include/drm/bridge/analogix_dp.h   |  3 ++
 5 files changed, 144 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..1fec91a 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,62 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }

+int analogix_dp_enable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   analogix_dp_send_psr_spd(dp, EDP_VSC_PSR_STATE_ACTIVE |
+EDP_VSC_PSR_CRC_VALUES_VALID);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
+
+int analogix_dp_disable_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   analogix_dp_send_psr_spd(dp, 0);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_disable_psr);
+
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_version;
+
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
+   dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
+
+   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
+}
+
+static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_en;
+
+   /* Disable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en &= ~DP_PSR_ENABLE;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Main-Link transmitter remains active during PSR active states */
+   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Enable psr function */
+   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
+DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   analogix_dp_enable_psr_crc(dp);
+}
+
 static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
 {
int i;
@@ -921,6 +977,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
*dp)

/* Enable video */
analogix_dp_start_video(dp);
+
+   dp->psr_support = analogix_dp_detect_sink_psr(dp);
+   if (dp->psr_support)
+   analogix_dp_enable_sink_psr(dp);
 }

 int analogix_dp_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index b456380..6ca5dde 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -177,6 +177,7 @@ struct analogix_dp_device {
int hpd_gpio;
boolforce_hpd;
unsigned char   edid[EDID_BLOCK_LENGTH * 2];
+   boolpsr_support;

struct analogix_dp_plat_data *plat_data;
 };
@@ -278,4 +279,7 @@ int analogix_dp_is_video_stream_on(struct 
analogix_dp_device *dp);
 void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp);
 void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_disable_scrambling(struct anal

[PATCH v4 2/4] drm/rockchip: add an common abstracted PSR driver

2016-07-14 Thread Yakir Yang
The PSR driver have exported four symbols for specific device driver:
- rockchip_drm_psr_register()
- rockchip_drm_psr_unregister()
- rockchip_drm_psr_enable()
- rockchip_drm_psr_disable()
- rockchip_drm_psr_flush()

Encoder driver should call the register/unregister interfaces to hook
itself into common PSR driver, encoder have implement the 'psr_set'
callback which use the set PSR state in hardware side.

Crtc driver would call the enable/disable interfaces when vblank is
enable/disable, after that the common PSR driver would call the encoder
registered callback to set the PSR state.

Fb driver would call the flush interface in 'fb->dirty' callback, this
helper function would force all PSR enabled encoders to exit from PSR
for 3 seconds.

Signed-off-by: Yakir Yang 
---
Changes in v4:
- Tuck the global "psr_list" & "psr_list_mutex" in struct rockchip_drm_private. 
(Sean)
- Move the access of "psr->state" under "psr->state_mutex"'s protect. (Sean)
- Let "psr->state = PSR_FLUSH" under "psr->state_mutex"'s protect. (Sean)
- Collect psr_enable() and psr_disable() into psr_set_state()
- s/5\ second/PSR_FLUSH_TIMEOUT/ (Sean)
- Flush the psr callback in vop_crtc_disable(). (Stéphane, reviewed in Google 
gerrit)

[https://chromium-review.googlesource.com/#/c/349084/6/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 475]
- Add the missing file head with license. (Stéphane, reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/357563/1/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
 at 3]

Changes in v3:
- split the psr flow into an common abstracted PSR driver
- implement the 'fb->dirty' callback function (Daniel)
- avoid to use notify to acqiure for vact event (Daniel)
- remove psr_active() callback which introduce in v2

Changes in v2: None

 drivers/gpu/drm/rockchip/Makefile   |   2 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   4 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  12 ++
 drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 223 
 drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  26 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  29 
 7 files changed, 298 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index 05d0713..9746365 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -3,7 +3,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-   rockchip_drm_gem.o rockchip_drm_vop.o
+   rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o

 obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index d665fb0..26c12b3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -156,6 +156,9 @@ static int rockchip_drm_bind(struct device *dev)

drm_dev->dev_private = private;

+   INIT_LIST_HEAD(>psr_list);
+   mutex_init(>psr_list_mutex);
+
drm_mode_config_init(drm_dev);

rockchip_drm_mode_config_init(drm_dev);
@@ -218,6 +221,7 @@ static int rockchip_drm_bind(struct device *dev)

if (is_support_iommu)
arm_iommu_release_mapping(mapping);
+
return 0;
 err_fbdev_fini:
rockchip_drm_fbdev_fini(drm_dev);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 239b830..9c34c9e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -61,6 +61,9 @@ struct rockchip_drm_private {
struct drm_gem_object *fbdev_bo;
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
struct drm_atomic_state *state;
+
+   struct list_head psr_list;
+   struct mutex psr_list_mutex;
 };

 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 20f12bc..36afd9c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -21,6 +21,7 @@

 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
+#include "rockchip_drm_psr.h"

 #define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)

@@ -66,9 +67,20 @@ static int rockchip_drm_fb_create_handle(struct 
drm_framebuffer *fb,
 rockchip_fb->obj[0], handl

[PATCH v4 1/4] drm/rockchip: vop: export line flag function

2016-07-14 Thread Yakir Yang
VOP have integrated a hardware counter which indicate the exact display
line that vop is scanning. And if we're interested in a specific line,
we can set the line number to vop line_flag register, and then vop would
generate a line_flag interrupt for it.

For example eDP PSR function is interested in the vertical blanking
period, then driver could set the line number to zero.

This patch have exported a symbol that allow other driver to listen the
line flag event with given timeout limit:
-  rockchip_drm_wait_line_flag()

Signed-off-by: Yakir Yang 
---
Changes in v4:
- Avoid the weird behavior in rockchip_drm_wait_line_flag(). (Sean)
- Make line_flag_num_x to an array. (Sean)
- Remove the unused vop_cfg_done() in vop_line_flag_irq_enable(). (Stephane, 
reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/349084/33/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 466]

Changes in v3:
- Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
- Add 'line_flag_num_0' for RK3288/RK3036
- Remove the notify for waiting line_flag event (Daniel)

Changes in v2:
- Introduce in v2, split VOP line flag changes out

 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 118 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   2 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   4 +
 4 files changed, 127 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..239b830 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -70,4 +70,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
+int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
+   unsigned int mstimeout);
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index c8a62a8..69d32f1 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -121,6 +121,8 @@ struct vop {
/* protected by dev->event_lock */
struct drm_pending_vblank_event *event;

+   struct completion line_flag_completion;
+
const struct vop_data *data;

uint32_t *regsbak;
@@ -431,6 +433,71 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+/*
+ * (1) each frame starts at the start of the Vsync pulse which is signaled by
+ * the "FRAME_SYNC" interrupt.
+ * (2) the active data region of each frame ends at dsp_vact_end
+ * (3) we should program this same number (dsp_vact_end) into 
dsp_line_frag_num,
+ *  to get "LINE_FLAG" interrupt at the end of the active on screen data.
+ *
+ * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
+ * Interrupts
+ * LINE_FLAG ---+
+ * FRAME_SYNC + |
+ *| |
+ *v v
+ *| Vsync | Vbp |  Vactive  | Vfp |
+ *^ ^   ^ ^
+ *| |   | |
+ *| |   | |
+ * dsp_vs_end + |   | |   VOP_DSP_VTOTAL_VS_END
+ * dsp_vact_start --+   | |   VOP_DSP_VACT_ST_END
+ * dsp_vact_end + |   VOP_DSP_VACT_ST_END
+ * dsp_total -+   VOP_DSP_VTOTAL_VS_END
+ */
+static bool vop_line_flag_irq_is_enabled(struct vop *vop)
+{
+   uint32_t line_flag_irq;
+   unsigned long flags;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   line_flag_irq = VOP_INTR_GET_TYPE(vop, enable, LINE_FLAG_INTR);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+
+   return !!line_flag_irq;
+}
+
+static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
+{
+   unsigned long flags;
+
+   if (WARN_ON(!vop->is_enabled))
+   return;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   VOP_CTRL_SET(vop, line_flag_num[0], line_num);
+   VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+}
+
+static void vop_line_flag_irq_disable(struct vop *vop)
+{
+   unsigned long flags;
+
+   if (WARN_ON(!vop->is_enabled))
+   return;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 0);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+}
+
 static void vop_enable(struct drm_crtc *crtc)
 {

[PATCH v4 0/4] Add PSR function support for Analogix/Rockchip DP

2016-07-14 Thread Yakir Yang

The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make a lots
of sense to save the power consumption.

This v3 version have splited an common PSR driver for Rockchip, which is
biggest changes from v2.

This thread is based on Mark's RK3399 VOP thread[0] and my RK3399 eDP
thread[1].

[0]: https://patchwork.kernel.org/patch/8886041/
[1]: https://patchwork.kernel.org/patch/9204497/


Changes in v4:
- Avoid the weird behavior in rockchip_drm_wait_line_flag(). (Sean)
- Make line_flag_num_x to an array. (Sean)
- Remove the unused vop_cfg_done() in vop_line_flag_irq_enable(). (Stephane, 
reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/349084/33/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 466]
- Tuck the global "psr_list" & "psr_list_mutex" in struct rockchip_drm_private. 
(Sean)
- Move the access of "psr->state" under "psr->state_mutex"'s protect. (Sean)
- Let "psr->state = PSR_FLUSH" under "psr->state_mutex"'s protect. (Sean)
- Collect psr_enable() and psr_disable() into psr_set_state()
- s/5\ second/PSR_FLUSH_TIMEOUT/ (Sean)
- Flush the psr callback in vop_crtc_disable(). (Stéphane, reviewed in Google 
gerrit)

[https://chromium-review.googlesource.com/#/c/349084/6/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
 at 475]
- Add the missing file head with license. (Stéphane, reviewed in Google gerrit)

[https://chromium-review.googlesource.com/#/c/357563/1/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
 at 3]
- Downgrade the PSR version print message to debug level. (Sean)
- Return 'void' instead of 'int' in analogix_dp_enable_sink_psr(). (Sean)
- Delete the unused read dpcd operations in analogix_dp_enable_sink_psr(). 
(Sean)
- Delete the arbitrary usleep_range in analogix_dp_enable_psr_crc. (Sean).
- Clean up the hardcoded values in analogix_dp_send_psr_spd(). (Sean)
- Rename "active/inactive" to "enable/disable". (Sean, Dominik)
- Keep set the PSR_VID_CRC_FLUSH gate in analogix_dp_enable_psr_crc().
- Return 'void' instead of 'int' in analogix_dp_psr_set(). (Sean)
- Pull the 10ms delay time out into a #define. (Sean)
- Improved the code of analogix_dp_psr_work(). (Sean)
- Indented with spaces for new numbers in rockchip_dp_device struct. 
(Stéphane, reviewed at Google gerrit)

[https://chromium-review.googlesource.com/#/c/349085/33/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 83]

Changes in v3:
- Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
- Add 'line_flag_num_0' for RK3288/RK3036
- Remove the notify for waiting line_flag event (Daniel)
- split the psr flow into an common abstracted PSR driver
- implement the 'fb->dirty' callback function (Daniel)
- avoid to use notify to acqiure for vact event (Daniel)
- remove psr_active() callback which introduce in v2
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments
- split the common psr logic into a seperate driver, make this to a
  simple sub-psr device driver.

Changes in v2:
- Introduce in v2, split VOP line flag changes out
- introduce in v2, splite the common Analogix DP changes out
- remove vblank notify out (Daniel)
- create a psr_active() callback in vop data struct.

Yakir Yang (4):
  drm/rockchip: vop: export line flag function
  drm/rockchip: add an common abstracted PSR driver
  drm/bridge: analogix_dp: add the PSR function support
  drm/rockchip: analogix_dp: implement PSR function

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  60 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |   4 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  |  49 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  |  28 +++
 drivers/gpu/drm/rockchip/Makefile  |   2 +-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c|  57 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c|   4 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h|   6 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c |  12 ++
 drivers/gpu/drm/rockchip/rockchip_drm_psr.c| 223 +
 drivers/gpu/drm/rockchip/rockchip_drm_psr.h|  26 +++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 147 ++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h|   2 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c|   4 +
 include/drm/bridge/analogix_dp.h   |   3 +
 15 files changed, 626 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h

-- 
1.9.1




[PATCH v1 5/6] drm/rockchip: dw_hdmi: introduce the VPLL clock setting

2016-07-13 Thread Yakir Yang
Heiko,

On 07/12/2016 10:27 PM, Heiko Stübner wrote:
> Hi Yakir,
>
> Am Montag, 11. Juli 2016, 19:05:49 schrieb Yakir Yang:
>> For RK3399 HDMI, there is an external clock need for HDMI PHY,
>> and it should keep the same clock rate with VOP DCLK.
>>
>> VPLL have supported the clock for HDMI PHY, but there is no
>> clock divider bewteen VPLL and HDMI PHY. So we need to set the
>> VPLL rate manually in HDMI driver.
> I don't think reserving the vpll for the hdmi at all times is the right way to
> go.
>
> While I do agree that reserving the VPLL (and NPLL on the rk3288) for graphics
> use looks like the right way, I think the core Rockchip drm driver should be
> responsible for managing it and also for deciding which output encoder gets to
> use it.
> While true that on the Chromebook device-types the edp is static and hdmi
> needs the broad range of dynamic frequencies, this is not necessarily the case
> for all future device types and/or socs.
>
> In the other thread we discussed adding that as rockchip,dclk-pll = <&...>; to
> the base display-subsystem node, Doug didn't manage to find time to respond 
> yet
> though - and is on vacation right now.

Great idea. Let a separate drm-pll driver to maintain all connector's 
clock requirement.

> I still believe that would be the best solution :-) .
>
>
> That property could list 1 or even 2 plls, depending on the soc or board
> layout - maybe someone frees up the cpll in some special layout or something.
> If none are listed, then the drm driver would need to cope with its available
> clocks.
>
> Implementation-wise you could even still keep your shortcut until we encounter
> a device with different , let the drm use the pll for hdmi only until someone
> comes up with a better concept, but still the binding should be correct and
> versatile from the start.

Someone should start to prepare the drm core pll driver, it's great idea.

BR,
- Yakir

>
> Heiko
>
>> ---
>>   .../bindings/display/rockchip/dw_hdmi-rockchip.txt |  3 ++-
>>   drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 25
>> +- 2 files changed, 26 insertions(+), 2 deletions(-)
>>
>> diff --git
>> a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
>> b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
>> index 4e573d2..4e23ca4 100644
>> ---
>> a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
>> +++
>> b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
>> @@ -17,7 +17,8 @@ Required properties:
>>
>>   Optional properties
>>   - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
>> -- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
>> +- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec",
>> +   phandle to the VPLL clock, name should be "vpll".
>>
>>   Example:
>>   hdmi: hdmi at ff98 {
>> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
>> b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 329099b..701bb73 100644
>> --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
>> +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
>> @@ -7,10 +7,12 @@
>>* (at your option) any later version.
>>*/
>>
>> +#include 
>> +#include 
>>   #include 
>>   #include 
>> -#include 
>>   #include 
>> +
>>   #include 
>>   #include 
>>   #include 
>> @@ -33,6 +35,7 @@ struct rockchip_hdmi {
>>  struct regmap *regmap;
>>  struct drm_encoder encoder;
>>  enum dw_hdmi_devtype dev_type;
>> +struct clk *vpll_clk;
>>   };
>>
>>   #define to_rockchip_hdmi(x)container_of(x, struct rockchip_hdmi, x)
>> @@ -145,6 +148,7 @@ static const struct dw_hdmi_phy_config
>> rockchip_phy_config[] = { static int rockchip_hdmi_parse_dt(struct
>> rockchip_hdmi *hdmi)
>>   {
>>  struct device_node *np = hdmi->dev->of_node;
>> +int ret;
>>
>>  hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>>  if (IS_ERR(hdmi->regmap)) {
>> @@ -152,6 +156,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi
>> *hdmi) return PTR_ERR(hdmi->regmap);
>>  }
>>
>> +hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
>> +if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
>> +hdmi->vpll_clk = NULL;
>> +} else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
>>

[PATCH v1 4/6] drm/rockchip: dw_hdmi: add RK3399 HDMI support

2016-07-13 Thread Yakir Yang
Philipp,

On 07/11/2016 07:51 PM, Philipp Zabel wrote:
> Am Montag, den 11.07.2016, 19:05 +0800 schrieb Yakir Yang:
>> RK3399 and RK3288 shared the same HDMI IP controller, only some light
>> difference with GRF configure.
>>
>> Signed-off-by: Yakir Yang 
> Reviewed-by: Philipp Zabel 

Thanks for your fast respond :-D
- Yakir

> regards
> Philipp
>
>
>
>




[PATCH v3 2/4] drm/rockchip: add an common abstracted PSR driver

2016-07-13 Thread Yakir Yang
Daniel,

On 07/12/2016 08:38 PM, Daniel Vetter wrote:
> On Fri, Jul 01, 2016 at 02:00:00PM -0400, Sean Paul wrote:
>> On Fri, Jul 1, 2016 at 5:19 AM, Yakir Yang  wrote:
>>> The PSR driver have exported four symbols for specific device driver:
>>> - rockchip_drm_psr_register()
>>> - rockchip_drm_psr_unregister()
>>> - rockchip_drm_psr_enable()
>>> - rockchip_drm_psr_disable()
>>> - rockchip_drm_psr_flush()
>>>
>>> Encoder driver should call the register/unregister interfaces to hook
>>> itself into common PSR driver, encoder have implement the 'psr_set'
>>> callback which use the set PSR state in hardware side.
>>>
>>> Crtc driver would call the enable/disable interfaces when vblank is
>>> enable/disable, after that the common PSR driver would call the encoder
>>> registered callback to set the PSR state.
>>>
>> This feels overly complicated. It seems like you could cut out a bunch
>> of code by just coding the psr functions into vop and
>> analogix_dp-rockchip. I suppose the only reason to keep it abstracted
>> would be if you plan on supporting psr in a different encoder or crtc
>> in rockchip, or if you're planning on moving this into drm core.
> Agreed on the layers of indirection. Also, you end up with 3 delayed
> timers in total:
> - defio timer from fbdev emulation
> - timer in this abstraction
> - delayed work in the psr backend driver
>
> I'd cut out at least the middle one.
>
> But since this seems to correctly use the ->dirty callback it gets my Ack
> either way ;-)

Aha, thanks :-D

- Yakir

> Cheers, Daniel
>
>> Perhaps others will disagree with this sentiment and this is the right
>> thing to do.
>>
>>> Fb driver would call the flush interface in 'fb->dirty' callback, this
>>> helper function would force all PSR enabled encoders to exit from PSR
>>> for 3 seconds.
>>>
>>> Signed-off-by: Yakir Yang 
>>> ---
>>> Changes in v3:
>>> - split the psr flow into an common abstracted PSR driver
>>> - implement the 'fb->dirty' callback function (Daniel)
>>> - avoid to use notify to acqiure for vact event (Daniel)
>>> - remove psr_active() callback which introduce in v2
>>>
>>> Changes in v2: None
>>>
>>>   drivers/gpu/drm/rockchip/Makefile   |   2 +-
>>>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  12 ++
>>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 200 
>>> 
>>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  12 ++
>>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  24 
>>>   5 files changed, 249 insertions(+), 1 deletion(-)
>>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
>>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h
>>>
>>> diff --git a/drivers/gpu/drm/rockchip/Makefile 
>>> b/drivers/gpu/drm/rockchip/Makefile
>>> index 05d0713..9746365 100644
>>> --- a/drivers/gpu/drm/rockchip/Makefile
>>> +++ b/drivers/gpu/drm/rockchip/Makefile
>>> @@ -3,7 +3,7 @@
>>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>>
>>>   rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
>>> -   rockchip_drm_gem.o rockchip_drm_vop.o
>>> +   rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
>>>   rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>>>
>>>   obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
>>> b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>>> index 20f12bc..0fec18f 100644
>>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>>> @@ -21,6 +21,7 @@
>>>
>>>   #include "rockchip_drm_drv.h"
>>>   #include "rockchip_drm_gem.h"
>>> +#include "rockchip_drm_psr.h"
>>>
>>>   #define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
>>>
>>> @@ -66,9 +67,20 @@ static int rockchip_drm_fb_create_handle(struct 
>>> drm_framebuffer *fb,
>>>   rockchip_fb->obj[0], handle);
>>>   }
>>>
>>> +static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
>>> +struct drm_file *file,
>>> +unsigned int flags, unsigned int color,
>>> +

[PATCH v3 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-13 Thread Yakir Yang
Sean,

On 07/12/2016 11:29 PM, Sean Paul wrote:
> On Thu, Jul 7, 2016 at 7:26 PM, Yakir Yang  wrote:
>> Sean,
>>
>> Thanks for your review.
>>
>>
>> On 07/02/2016 03:46 AM, Sean Paul wrote:
>>> On Fri, Jul 1, 2016 at 5:19 AM, Yakir Yang  wrote:
>>>> The full name of PSR is Panel Self Refresh, panel device could refresh
>>>> itself with the hardware framebuffer in panel, this would make lots of
>>>> sense to save the power consumption.
>>>>
>>>> This patch have exported two symbols for platform driver to implement
>>>> the PSR function in hardware side:
>>>> - analogix_dp_active_psr()
>>>> - analogix_dp_inactive_psr()
>>>>
>>>> Signed-off-by: Yakir Yang 
>>>> ---
>>>> Changes in v3:
>>>> - split analogix_dp_enable_psr(), make it more clearly
>>>>   analogix_dp_detect_sink_psr()
>>>>   analogix_dp_enable_sink_psr()
>>>> - remove some nosie register setting comments
>>>>
>>>> Changes in v2:
>>>> - introduce in v2, splite the common Analogix DP changes out
>>>>
>>>>drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 64
>>>> ++
>>>>drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++
>>>>drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 54
>>>> ++
>>>>drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 28 ++
>>>>include/drm/bridge/analogix_dp.h   |  3 +
>>>>5 files changed, 153 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>>> index 32715da..b557097 100644
>>>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>>> @@ -97,6 +97,66 @@ static int analogix_dp_detect_hpd(struct
>>>> analogix_dp_device *dp)
>>>>   return 0;
>>>>}
>>>>
>>>> +int analogix_dp_active_psr(struct device *dev)
>>>> +{
>>>> +   struct analogix_dp_device *dp = dev_get_drvdata(dev);
>>>> +
>>>> +   if (!dp->psr_support)
>>>> +   return -EINVAL;
>>>> +
>>>> +   analogix_dp_send_psr_spd(dp, EDP_VSC_PSR_STATE_ACTIVE |
>>>> +EDP_VSC_PSR_CRC_VALUES_VALID);
>>>> +   return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(analogix_dp_active_psr);
>>>> +
>>>> +int analogix_dp_inactive_psr(struct device *dev)
>>>> +{
>>>> +   struct analogix_dp_device *dp = dev_get_drvdata(dev);
>>>> +
>>>> +   if (!dp->psr_support)
>>>> +   return -EINVAL;
>>>> +
>>>> +   analogix_dp_send_psr_spd(dp, 0);
>>>> +   return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(analogix_dp_inactive_psr);
>>>> +
>>>> +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
>>>> +{
>>>> +   unsigned char psr_version;
>>>> +
>>>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT,
>>>> _version);
>>>> +   dev_info(dp->dev, "Panel PSR version : %x\n", psr_version);
>>>> +
>>> This info message is likely to be spammy since it's printed everytime
>>> the panel toggle on. Perhaps downgrade to debug level.
>>
>> Okay, done.
>>
>>>> +   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
>>>> +}
>>>> +
>>>> +static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
>>> Return type is int, but the function never fails and you don't check
>>> the return value when calling it. Seems like this should be void.
>>
>> Done.
>>
>>>> +{
>>>> +   unsigned char psr_en;
>>>> +
>>>> +   /* Disable psr function */
>>>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
>>>> +   psr_en &= ~DP_PSR_ENABLE;
>>>> +   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>>>> +
>>>> +   /* Main-Link transmitter remains active during PSR active states
>>>> */
>>>> +   analogix_dp_read_b

[PATCH v1 6/6] drm/rockchip: dw_hdmi: introduce the pclk for grf

2016-07-11 Thread Yakir Yang
For RK3399's GRF module, if we want to operate the graphic related grf
registers, we need to enable the pclk_vio_grf which supply power for VIO
GRF IOs, so it's better to introduce an optional grf clock in driver.

Signed-off-by: Yakir Yang 
---
 .../bindings/display/rockchip/dw_hdmi-rockchip.txt   |  3 ++-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c  | 20 
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
index 4e23ca4..e22d70f 100644
--- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
+++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
@@ -18,7 +18,8 @@ Required properties:
 Optional properties
 - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
 - clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec",
-  phandle to the VPLL clock, name should be "vpll".
+  phandle to the VPLL clock, name should be "vpll",
+  phandle to the GRF clock, name should be "grf".

 Example:
 hdmi: hdmi at ff98 {
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 701bb73..69e6efb 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -36,6 +36,7 @@ struct rockchip_hdmi {
struct drm_encoder encoder;
enum dw_hdmi_devtype dev_type;
struct clk *vpll_clk;
+   struct clk *grf_clk;
 };

 #define to_rockchip_hdmi(x)container_of(x, struct rockchip_hdmi, x)
@@ -166,6 +167,16 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi 
*hdmi)
return PTR_ERR(hdmi->vpll_clk);
}

+   hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf");
+   if (PTR_ERR(hdmi->grf_clk) == -ENOENT) {
+   hdmi->grf_clk = NULL;
+   } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) {
+   return -EPROBE_DEFER;
+   } else if (IS_ERR(hdmi->grf_clk)) {
+   dev_err(hdmi->dev, "failed to get grf clock\n");
+   return PTR_ERR(hdmi->grf_clk);
+   }
+
ret = clk_prepare_enable(hdmi->vpll_clk);
if (ret) {
dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret);
@@ -225,6 +236,7 @@ static void dw_hdmi_rockchip_encoder_enable(struct 
drm_encoder *encoder)
u32 lcdsel_grf_reg, lcdsel_mask;
u32 val;
int mux;
+   int ret;

switch (hdmi->dev_type) {
case RK3288_HDMI:
@@ -245,9 +257,17 @@ static void dw_hdmi_rockchip_encoder_enable(struct 
drm_encoder *encoder)
else
val = HIWORD_UPDATE(0, lcdsel_mask);

+   ret = clk_prepare_enable(hdmi->grf_clk);
+   if (ret < 0) {
+   dev_err(hdmi->dev, "failed to enable grfclk %d\n", ret);
+   return;
+   }
+
regmap_write(hdmi->regmap, lcdsel_grf_reg, val);
dev_dbg(hdmi->dev, "vop %s output to hdmi\n",
(mux) ? "LIT" : "BIG");
+
+   clk_disable_unprepare(hdmi->grf_clk);
 }

 static int
-- 
1.9.1




[PATCH v1 5/6] drm/rockchip: dw_hdmi: introduce the VPLL clock setting

2016-07-11 Thread Yakir Yang
For RK3399 HDMI, there is an external clock need for HDMI PHY,
and it should keep the same clock rate with VOP DCLK.

VPLL have supported the clock for HDMI PHY, but there is no
clock divider bewteen VPLL and HDMI PHY. So we need to set the
VPLL rate manually in HDMI driver.

Signed-off-by: Yakir Yang 
---
 .../bindings/display/rockchip/dw_hdmi-rockchip.txt |  3 ++-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 25 +-
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
index 4e573d2..4e23ca4 100644
--- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
+++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
@@ -17,7 +17,8 @@ Required properties:

 Optional properties
 - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
-- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
+- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec",
+  phandle to the VPLL clock, name should be "vpll".

 Example:
 hdmi: hdmi at ff98 {
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 329099b..701bb73 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -7,10 +7,12 @@
  * (at your option) any later version.
  */

+#include 
+#include 
 #include 
 #include 
-#include 
 #include 
+
 #include 
 #include 
 #include 
@@ -33,6 +35,7 @@ struct rockchip_hdmi {
struct regmap *regmap;
struct drm_encoder encoder;
enum dw_hdmi_devtype dev_type;
+   struct clk *vpll_clk;
 };

 #define to_rockchip_hdmi(x)container_of(x, struct rockchip_hdmi, x)
@@ -145,6 +148,7 @@ static const struct dw_hdmi_phy_config 
rockchip_phy_config[] = {
 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 {
struct device_node *np = hdmi->dev->of_node;
+   int ret;

hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
if (IS_ERR(hdmi->regmap)) {
@@ -152,6 +156,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi 
*hdmi)
return PTR_ERR(hdmi->regmap);
}

+   hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
+   if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
+   hdmi->vpll_clk = NULL;
+   } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
+   return -EPROBE_DEFER;
+   } else if (IS_ERR(hdmi->vpll_clk)) {
+   dev_err(hdmi->dev, "failed to get grf clock\n");
+   return PTR_ERR(hdmi->vpll_clk);
+   }
+
+   ret = clk_prepare_enable(hdmi->vpll_clk);
+   if (ret) {
+   dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret);
+   return ret;
+   }
+
return 0;
 }

@@ -194,6 +214,9 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct 
drm_encoder *encoder,
  struct drm_display_mode *mode,
  struct drm_display_mode *adj_mode)
 {
+   struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
+
+   clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000);
 }

 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
-- 
1.9.1




[PATCH v1 4/6] drm/rockchip: dw_hdmi: add RK3399 HDMI support

2016-07-11 Thread Yakir Yang
RK3399 and RK3288 shared the same HDMI IP controller, only some light
difference with GRF configure.

Signed-off-by: Yakir Yang 
---
 .../devicetree/bindings/display/bridge/dw_hdmi.txt |  1 +
 .../bindings/display/rockchip/dw_hdmi-rockchip.txt |  3 +-
 drivers/gpu/drm/bridge/dw-hdmi.c   |  2 +-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 45 ++
 include/drm/bridge/dw_hdmi.h   |  6 +++
 5 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt 
b/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
index dc1452f..f50d4d5 100644
--- a/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
+++ b/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
@@ -6,6 +6,7 @@ Required properties:
* "fsl,imx6q-hdmi"
* "fsl,imx6dl-hdmi"
* "rockchip,rk3288-dw-hdmi"
+   * "rockchip,rk3399-dw-hdmi"
 - reg: Physical base address and length of the controller's registers.
 - interrupts: The HDMI interrupt number
 - clocks, clock-names : must have the phandles to the HDMI iahb and isfr 
clocks,
diff --git 
a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
index 668091f..4e573d2 100644
--- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
+++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt
@@ -2,7 +2,8 @@ Rockchip specific extensions to the Synopsys Designware HDMI
 

 Required properties:
-- compatible: "rockchip,rk3288-dw-hdmi";
+- compatible: "rockchip,rk3288-dw-hdmi",
+ "rockchip,rk3399-dw-hdmi";
 - reg: Physical base address and length of the controller's registers.
 - clocks: phandle to hdmi iahb and isfr clocks.
 - clock-names: should be "iahb" "isfr"
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 70b1f7d..29f855a 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -833,7 +833,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, 
unsigned char prep,
dw_hdmi_phy_gen2_txpwron(hdmi, 1);
dw_hdmi_phy_gen2_pddq(hdmi, 0);

-   if (hdmi->dev_type == RK3288_HDMI)
+   if (is_rockchip(hdmi->dev_type))
dw_hdmi_phy_enable_spare(hdmi, 1);

/*Wait for PHY PLL lock */
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 8cb9ed2..329099b 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -21,13 +21,18 @@
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_vop.h"

-#define GRF_SOC_CON60x025c
-#define HDMI_SEL_VOP_LIT(1 << 4)
+#define RK3288_GRF_SOC_CON60x025C
+#define RK3288_HDMI_LCDC_SEL   BIT(4)
+#define RK3399_GRF_SOC_CON20   0x6250
+#define RK3399_HDMI_LCDC_SEL   BIT(6)
+
+#define HIWORD_UPDATE(val, mask)   (val | (mask) << 16)

 struct rockchip_hdmi {
struct device *dev;
struct regmap *regmap;
struct drm_encoder encoder;
+   enum dw_hdmi_devtype dev_type;
 };

 #define to_rockchip_hdmi(x)container_of(x, struct rockchip_hdmi, x)
@@ -194,16 +199,30 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct 
drm_encoder *encoder,
 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
 {
struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
+   u32 lcdsel_grf_reg, lcdsel_mask;
u32 val;
int mux;

+   switch (hdmi->dev_type) {
+   case RK3288_HDMI:
+   lcdsel_grf_reg = RK3288_GRF_SOC_CON6;
+   lcdsel_mask = RK3288_HDMI_LCDC_SEL;
+   break;
+   case RK3399_HDMI:
+   lcdsel_grf_reg = RK3399_GRF_SOC_CON20;
+   lcdsel_mask = RK3399_HDMI_LCDC_SEL;
+   break;
+   default:
+   return;
+   };
+
mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
if (mux)
-   val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
+   val = HIWORD_UPDATE(lcdsel_mask, lcdsel_mask);
else
-   val = HDMI_SEL_VOP_LIT << 16;
+   val = HIWORD_UPDATE(0, lcdsel_mask);

-   regmap_write(hdmi->regmap, GRF_SOC_CON6, val);
+   regmap_write(hdmi->regmap, lcdsel_grf_reg, val);
dev_dbg(hdmi->dev, "vop %s output to hdmi\n",
(mux) ? "LIT" : "BIG");
 }
@@ -229,7 +248,7 @@ static const struct drm_encoder_helper_funcs 
dw_hdmi_rockchip_encoder_helper_fun
.atomic_check = dw_hdmi_rockchip_encoder_atomic_check,
 };

-static co

[PATCH v1 3/6] drm/rockchip: dw_hdmi: Use auto-generated tables

2016-07-11 Thread Yakir Yang
From: Douglas Anderson <diand...@chromium.org>

The previous tables for mpll_cfg and curr_ctrl were created using the
20-pages of example settings provided by the PHY vendor.  Those
example settings weren't particularly dense, so there were places
where we were guessing what the settings would be for 10-bit and
12-bit (not that we use those anyway).  It was also always a lot of
extra work every time we wanted to add a new clock rate since we had
to cross-reference several tables.

In <http://crosreview.com/285855> I've gone through the work to figure
out how to generate this table automatically.  Let's now use the
automatically generated table and then we'll never need to look at it
again.

We only support 8-bit mode right now and only support a small number
of clock rates and and I've verified that the only 8-bit rate that was
affected was 148.5.  That mode appears to have been wrong in the old
table.

Signed-off-by: Douglas Anderson 
Signed-off-by: Yakir Yang 
Reviewed-by: Stéphane Marchesin 
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 130 +++-
 1 file changed, 69 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index cdb63ac..8cb9ed2 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -34,80 +34,88 @@ struct rockchip_hdmi {

 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
{
-   2700, {
-   { 0x00b3, 0x},
-   { 0x2153, 0x},
-   { 0x40f3, 0x}
+   30666000, {
+   { 0x00b3, 0x },
+   { 0x2153, 0x },
+   { 0x40f3, 0x },
},
-   }, {
-   3600, {
-   { 0x00b3, 0x},
-   { 0x2153, 0x},
-   { 0x40f3, 0x}
+   },  {
+   3680, {
+   { 0x00b3, 0x },
+   { 0x2153, 0x },
+   { 0x40a2, 0x0001 },
},
-   }, {
-   4000, {
-   { 0x00b3, 0x},
-   { 0x2153, 0x},
-   { 0x40f3, 0x}
+   },  {
+   4600, {
+   { 0x00b3, 0x },
+   { 0x2142, 0x0001 },
+   { 0x40a2, 0x0001 },
},
-   }, {
-   5400, {
-   { 0x0072, 0x0001},
-   { 0x2142, 0x0001},
-   { 0x40a2, 0x0001},
+   },  {
+   61333000, {
+   { 0x0072, 0x0001 },
+   { 0x2142, 0x0001 },
+   { 0x40a2, 0x0001 },
},
-   }, {
-   6500, {
-   { 0x0072, 0x0001},
-   { 0x2142, 0x0001},
-   { 0x40a2, 0x0001},
+   },  {
+   7360, {
+   { 0x0072, 0x0001 },
+   { 0x2142, 0x0001 },
+   { 0x4061, 0x0002 },
},
-   }, {
-   6600, {
-   { 0x013e, 0x0003},
-   { 0x217e, 0x0002},
-   { 0x4061, 0x0002}
+   },  {
+   9200, {
+   { 0x0072, 0x0001 },
+   { 0x2145, 0x0002 },
+   { 0x4061, 0x0002 },
+   },
+   },  {
+   122666000, {
+   { 0x0051, 0x0002 },
+   { 0x2145, 0x0002 },
+   { 0x4061, 0x0002 },
},
-   }, {
-   7425, {
-   { 0x0072, 0x0001},
-   { 0x2145, 0x0002},
-   { 0x4061, 0x0002}
+   },  {
+   14720, {
+   { 0x0051, 0x0002 },
+   { 0x2145, 0x0002 },
+   { 0x4064, 0x0003 },
},
-   }, {
-   8350, {
-   { 0x0072, 0x0001},
+   },  {
+   18400, {
+   { 0x0051, 0x0002 },
+   { 0x214c, 0x0003 },
+   { 0x4064, 0x0003 },
},
-   }, {
-   10800, {
-   { 0x0051, 0x0002},
-   { 0x2145, 0x0002},
-   { 0x4061, 0x0002}
+   },  {
+   22000, {
+   { 0x0040, 0x0003 },
+   { 0x214c, 0x0003 },
+   { 0x4064, 0x0003 },
},
-   }, {
-   10650, {
-   { 0x0051, 0x0002},
-   { 0x

[PATCH v1 2/6] drm/rockchip: dw_hdmi: adjust cklvl & txlvl for RF/EMI

2016-07-11 Thread Yakir Yang
Dut to the high HDMI signal voltage driver, Mickey have meet
a serious RF/EMI problem, so we decided to reduce HDMI signal
voltage to a proper value.

The default params for phy is cklvl = 20 & txlvl = 13 (RF/EMI failed)
  ck: lvl = 13, term=100, vlo = 2.71, vhi=3.14, vswing = 0.43
  tx: lvl = 20, term=100, vlo = 2.81, vhi=3.16, vswing = 0.35

1. We decided to reduce voltage value to lower, but VSwing still
keep high, RF/EMI have been improved but still failed.
   ck: lvl =  6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50
   tx: lvl =  6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50

2. We try to keep voltage value and vswing both lower, then RF/EMI
test all passed  ;)
   ck: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40
   tx: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40
When we back to run HDMI different test and single-end test, we see
different test passed, but signle-end test failed. The oscilloscope
show that simgle-end clock's VL value is 1.78v (which remind LowLimit
should not lower then 2.6v).

3. That's to say there are some different between PHY document and
measure value. And according to experiment 2 results, we need to
higher clock voltage and lower data voltage, then we can keep RF/EMI
satisfied and single-end & differen test passed.
  ck: lvl =  9, term=100, vlo = 2.65, vhi=3.12, vswing = 0.47
  tx: lvl = 16, term=100, vlo = 2.75, vhi=3.15, vswing = 0.39

Signed-off-by: Yakir Yang 
Reviewed-by: Douglas Anderson 
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index a621118..cdb63ac 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -124,7 +124,7 @@ static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
 static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
/*pixelclk   symbol   term   vlev*/
{ 7425,  0x8009, 0x0004, 0x0272},
-   { 14850, 0x802b, 0x0004, 0x028d},
+   { 16500, 0x802b, 0x0004, 0x0209},
{ 29700, 0x8039, 0x0005, 0x028d},
{ ~0UL,  0x, 0x, 0x}
 };
-- 
1.9.1




[PATCH v1 1/6] drm/rockchip: dw_hdmi: Set cur_ctr to 0 always

2016-07-11 Thread Yakir Yang
From: Douglas Anderson <diand...@chromium.org>

Jitter was improved by lowering the MPLL bandwidth to account for high
frequency noise in the rk3288 PLL.  In each case MPLL bandwidth was
lowered only enough to get us a comfortable margin.  We believe that
lowering the bandwidth like this is safe given sufficient testing.

Signed-off-by: Douglas Anderson 
Signed-off-by: Yakir Yang 
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++--
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 801110f..a621118 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -115,20 +115,8 @@ static const struct dw_hdmi_mpll_config 
rockchip_mpll_cfg[] = {
 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
/*  pixelclkbpp8bpp10   bpp12 */
{
-   4000,  { 0x0018, 0x0018, 0x0018 },
-   }, {
-   6500,  { 0x0028, 0x0028, 0x0028 },
-   }, {
-   6600,  { 0x0038, 0x0038, 0x0038 },
-   }, {
-   7425,  { 0x0028, 0x0038, 0x0038 },
-   }, {
-   8350,  { 0x0028, 0x0038, 0x0038 },
-   }, {
-   14625, { 0x0038, 0x0038, 0x0038 },
-   }, {
-   14850, { 0x, 0x0038, 0x0038 },
-   }, {
+   6, { 0x, 0x, 0x },
+   },  {
~0UL,  { 0x, 0x, 0x},
}
 };
-- 
1.9.1




[PATCH v1 0/6] Add RK3399 HDMI Support

2016-07-11 Thread Yakir Yang
Mark,

RK3399 and RK3288 shared the same HDMI IP controller, only some
light difference with GRF configure, and an external VPLL clock
need to configure.

Thanks,
- Yakir


Douglas Anderson (2):
  drm/rockchip: dw_hdmi: Set cur_ctr to 0 always
  drm/rockchip: dw_hdmi: Use auto-generated tables

Yakir Yang (4):
  drm/rockchip: dw_hdmi: adjust cklvl & txlvl for RF/EMI
  drm/rockchip: dw_hdmi: add RK3399 HDMI support
  drm/rockchip: dw_hdmi: introduce the VPLL clock setting
  drm/rockchip: dw_hdmi: introduce the pclk for grf

 .../devicetree/bindings/display/bridge/dw_hdmi.txt |   1 +
 .../bindings/display/rockchip/dw_hdmi-rockchip.txt |   7 +-
 drivers/gpu/drm/bridge/dw-hdmi.c   |   2 +-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c| 238 +
 include/drm/bridge/dw_hdmi.h   |   6 +
 5 files changed, 167 insertions(+), 87 deletions(-)

-- 
1.9.1




[PATCH v3 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-08 Thread Yakir Yang


On 07/08/2016 10:26 AM, Yakir Yang wrote:
> Sean,
>
> Thanks for your review.
>
> On 07/02/2016 03:46 AM, Sean Paul wrote:
>> On Fri, Jul 1, 2016 at 5:19 AM, Yakir Yang  wrote:
>>> The full name of PSR is Panel Self Refresh, panel device could refresh
>>> itself with the hardware framebuffer in panel, this would make lots of
>>> sense to save the power consumption.
>>>
>>> This patch have exported two symbols for platform driver to implement
>>> the PSR function in hardware side:
>>> - analogix_dp_active_psr()
>>> - analogix_dp_inactive_psr()
>>>
>>> Signed-off-by: Yakir Yang 
>>> ---
>>> Changes in v3:
>>> - split analogix_dp_enable_psr(), make it more clearly
>>>  analogix_dp_detect_sink_psr()
>>>  analogix_dp_enable_sink_psr()
>>> - remove some nosie register setting comments
>>>
>>> Changes in v2:
>>> - introduce in v2, splite the common Analogix DP changes out
>>>
>>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 64 
>>> ++
>>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++
>>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 54 
>>> ++
>>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 28 ++
>>>   include/drm/bridge/analogix_dp.h   |  3 +
>>>   5 files changed, 153 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>> index 32715da..b557097 100644
>>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>>> @@ -97,6 +97,66 @@ static int analogix_dp_detect_hpd(struct 
>>> analogix_dp_device *dp)
>>>  return 0;
>>>   }
>>>
>>> +int analogix_dp_active_psr(struct device *dev)
>>> +{
>>> +   struct analogix_dp_device *dp = dev_get_drvdata(dev);
>>> +
>>> +   if (!dp->psr_support)
>>> +   return -EINVAL;
>>> +
>>> +   analogix_dp_send_psr_spd(dp, EDP_VSC_PSR_STATE_ACTIVE |
>>> + EDP_VSC_PSR_CRC_VALUES_VALID);
>>> +   return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(analogix_dp_active_psr);
>>> +
>>> +int analogix_dp_inactive_psr(struct device *dev)
>>> +{
>>> +   struct analogix_dp_device *dp = dev_get_drvdata(dev);
>>> +
>>> +   if (!dp->psr_support)
>>> +   return -EINVAL;
>>> +
>>> +   analogix_dp_send_psr_spd(dp, 0);
>>> +   return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(analogix_dp_inactive_psr);
>>> +
>>> +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
>>> +{
>>> +   unsigned char psr_version;
>>> +
>>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, 
>>> _version);
>>> +   dev_info(dp->dev, "Panel PSR version : %x\n", psr_version);
>>> +
>> This info message is likely to be spammy since it's printed everytime
>> the panel toggle on. Perhaps downgrade to debug level.
>
> Okay, done.
>
>>> +   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
>>> +}
>>> +
>>> +static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
>> Return type is int, but the function never fails and you don't check
>> the return value when calling it. Seems like this should be void.
>
> Done.
>
>>> +{
>>> +   unsigned char psr_en;
>>> +
>>> +   /* Disable psr function */
>>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
>>> +   psr_en &= ~DP_PSR_ENABLE;
>>> +   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>>> +
>>> +   /* Main-Link transmitter remains active during PSR active 
>>> states */
>>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
>>> +   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
>> Why read psr_en if you're just going to overwrite it? Perhaps you 
>> meant |= here.
>>
>
> Yes, it's my mistaken, no need to read the DP_PSR_EN_CFG, just 
> configure it directly is enough.
>
>>> + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>>> +
>>> +   /* Enable psr function */
>>> +   analogix_dp_r

[PATCH v3 4/4] drm/rockchip: analogix_dp: implement PSR function

2016-07-08 Thread Yakir Yang
Sean,

On 07/02/2016 04:05 AM, Sean Paul wrote:
> On Fri, Jul 1, 2016 at 5:19 AM, Yakir Yang  wrote:
>> Alway enable the PSR function for Rockchip analogix_dp driver. If panel
>> don't support PSR, then the core analogix_dp would ignore this setting.
>>
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v3:
>> - split the common psr logic into a seperate driver, make this to a
>>simple sub-psr device driver.
>>
>> Changes in v2:
>> - remove vblank notify out (Daniel)
>> - create a psr_active() callback in vop data struct.
>>
>>   drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 52 
>> +
>>   1 file changed, 52 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
>> b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> index e81e19a..80a60a6 100644
>> --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>> @@ -32,6 +32,7 @@
>>   #include 
>>
>>   #include "rockchip_drm_drv.h"
>> +#include "rockchip_drm_psr.h"
>>   #include "rockchip_drm_vop.h"
>>
>>   #define RK3288_GRF_SOC_CON60x25c
>> @@ -68,11 +69,53 @@ struct rockchip_dp_device {
>>  struct regmap*grf;
>>  struct reset_control *rst;
>>
>> +   struct delayed_work  psr_work;
>> +   unsigned int psr_state;
>> +
>>  const struct rockchip_dp_chip_data *data;
>>
>>  struct analogix_dp_plat_data plat_data;
>>   };
>>
>> +static int analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
> Again, this function doesn't fail, but its return type is int.
> Fortunately you don't check the return in rockchip_drm_psr.c, so this
> also seems like a good void candidate.

Okay, done.

>> +{
>> +   struct rockchip_dp_device *dp = to_dp(encoder);
>> +
>> +   dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
>> +
>> +   if (enabled)
>> +   dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
>> +   else
>> +   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
>> +
>> +   schedule_delayed_work(>psr_work, msecs_to_jiffies(10));
> Pull 10 out into a #define

Done

>> +
>> +   return 0;
>> +}
>> +
>> +static void analogix_dp_psr_work(struct work_struct *work)
>> +{
>> +   struct rockchip_dp_device *dp =
>> +   container_of(work, typeof(*dp), 
>> psr_work.work);
>> +   struct drm_crtc *crtc = dp->encoder.crtc;
>> +   int psr_state = dp->psr_state;
>> +   int vact_end;
>> +   int ret;
>> +
>> +   if (!crtc)
>> +   return;
>> +
>> +   vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
>> crtc->mode.vdisplay;
>> +
>> +   ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end, 100);
>
> Pull 100 out into a #define
>

Done.

>> +   if (ret == 0) {
> if (ret) {
>  dev_err(... "line flag interrupt did not arrive");
>  return;
> }

Done.

Thanks
- Yakir

>> +   if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
>> +   analogix_dp_active_psr(dp->dev);
>> +   else
>> +   analogix_dp_inactive_psr(dp->dev);
>> +   }
>> +}
>> +
>>   static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
>>   {
>>  reset_control_assert(dp->rst);
>> @@ -340,12 +383,21 @@ static int rockchip_dp_bind(struct device *dev, struct 
>> device *master,
>>  dp->plat_data.power_off = rockchip_dp_powerdown;
>>  dp->plat_data.get_modes = rockchip_dp_get_modes;
>>
>> +   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
>> +   INIT_DELAYED_WORK(>psr_work, analogix_dp_psr_work);
>> +
>> +   rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
>> +
>>  return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
>>   }
>>
>>   static void rockchip_dp_unbind(struct device *dev, struct device *master,
>> void *data)
>>   {
>> +   struct rockchip_dp_device *dp = dev_get_drvdata(dev);
>> +
>> +   rockchip_drm_psr_unregister(>encoder);
>> +
>>  return analogix_dp_unbind(dev, master, data);
>>   }
>>
>> --
>> 1.9.1
>>
>>
>
>




[PATCH v3 1/4] drm/rockchip: vop: export line flag function

2016-07-08 Thread Yakir Yang
Sean,

On 07/01/2016 11:32 PM, Sean Paul wrote:
> On Fri, Jul 1, 2016 at 11:30 AM, Sean Paul  wrote:
>> On Fri, Jul 1, 2016 at 5:19 AM, Yakir Yang  wrote:
>>> VOP have integrated a hardware counter which indicate the exact display
>>> line that vop is scanning. And if we're interested in a specific line,
>>> we can set the line number to vop line_flag register, and then vop would
>>> generate a line_flag interrupt for it.
>>>
>>> For example eDP PSR function is interested in the vertical blanking
>>> period, then driver could set the line number to zero.
>>>
>>> This patch have exported a symbol that allow other driver to listen the
>>> line flag event with given timeout limit:
>>> -  rockchip_drm_wait_line_flag()
>>>
>>> Signed-off-by: Yakir Yang 
>>> ---
>>> Changes in v3:
>>> - Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
>>> - Add 'line_flag_num_0' for RK3288/RK3036
>>> - Remove the notify for waiting line_flag event (Daniel)
>>>
>>> Changes in v2:
>>> - Introduce in v2, split VOP line flag changes out
>>>
>>>   drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
>>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 103 
>>> 
>>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   3 +
>>>   drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   4 ++
>>>   4 files changed, 113 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
>>> b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>>> index ea39329..239b830 100644
>>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
>>> @@ -70,4 +70,7 @@ int rockchip_drm_dma_attach_device(struct drm_device 
>>> *drm_dev,
>>> struct device *dev);
>>>   void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
>>>  struct device *dev);
>>> +int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int 
>>> line_num,
>>> +   unsigned int mstimeout);
>>> +
>>>   #endif /* _ROCKCHIP_DRM_DRV_H_ */
>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
>>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> index c8a62a8..cd3cac5 100644
>>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>> @@ -121,6 +121,8 @@ struct vop {
>>>  /* protected by dev->event_lock */
>>>  struct drm_pending_vblank_event *event;
>>>
>>> +   struct completion line_flag_completion;
>>> +
>>>  const struct vop_data *data;
>>>
>>>  uint32_t *regsbak;
>>> @@ -431,6 +433,59 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
>>> *vop)
>>>  spin_unlock_irqrestore(>irq_lock, flags);
>>>   }
>>>
>>> +/*
>>> + * (1) each frame starts at the start of the Vsync pulse which is signaled 
>>> by
>>> + * the "FRAME_SYNC" interrupt.
>>> + * (2) the active data region of each frame ends at dsp_vact_end
>>> + * (3) we should program this same number (dsp_vact_end) into 
>>> dsp_line_frag_num,
>>> + *  to get "LINE_FLAG" interrupt at the end of the active on screen 
>>> data.
>>> + *
>>> + * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
>>> + * Interrupts
>>> + * LINE_FLAG ---+
>>> + * FRAME_SYNC + |
>>> + *| |
>>> + *v v
>>> + *| Vsync | Vbp |  Vactive  | Vfp |
>>> + *^ ^   ^ ^
>>> + *| |   | |
>>> + *| |   | |
>>> + * dsp_vs_end + |   | |   VOP_DSP_VTOTAL_VS_END
>>> + * dsp_vact_start --+   | |   VOP_DSP_VACT_ST_END
>>> + * dsp_vact_end + |   VOP_DSP_VACT_ST_END
>>> + * dsp_total -+   VOP_DSP_VTOTAL_VS_END
>>> + */
>>> +
>>> +static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
>>> +{
>>> +

[PATCH v3 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-08 Thread Yakir Yang
Sean,

Thanks for your review.

On 07/02/2016 03:46 AM, Sean Paul wrote:
> On Fri, Jul 1, 2016 at 5:19 AM, Yakir Yang  wrote:
>> The full name of PSR is Panel Self Refresh, panel device could refresh
>> itself with the hardware framebuffer in panel, this would make lots of
>> sense to save the power consumption.
>>
>> This patch have exported two symbols for platform driver to implement
>> the PSR function in hardware side:
>> - analogix_dp_active_psr()
>> - analogix_dp_inactive_psr()
>>
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v3:
>> - split analogix_dp_enable_psr(), make it more clearly
>>  analogix_dp_detect_sink_psr()
>>  analogix_dp_enable_sink_psr()
>> - remove some nosie register setting comments
>>
>> Changes in v2:
>> - introduce in v2, splite the common Analogix DP changes out
>>
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 64 
>> ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 54 ++
>>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 28 ++
>>   include/drm/bridge/analogix_dp.h   |  3 +
>>   5 files changed, 153 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
>> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 32715da..b557097 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -97,6 +97,66 @@ static int analogix_dp_detect_hpd(struct 
>> analogix_dp_device *dp)
>>  return 0;
>>   }
>>
>> +int analogix_dp_active_psr(struct device *dev)
>> +{
>> +   struct analogix_dp_device *dp = dev_get_drvdata(dev);
>> +
>> +   if (!dp->psr_support)
>> +   return -EINVAL;
>> +
>> +   analogix_dp_send_psr_spd(dp, EDP_VSC_PSR_STATE_ACTIVE |
>> +EDP_VSC_PSR_CRC_VALUES_VALID);
>> +   return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(analogix_dp_active_psr);
>> +
>> +int analogix_dp_inactive_psr(struct device *dev)
>> +{
>> +   struct analogix_dp_device *dp = dev_get_drvdata(dev);
>> +
>> +   if (!dp->psr_support)
>> +   return -EINVAL;
>> +
>> +   analogix_dp_send_psr_spd(dp, 0);
>> +   return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(analogix_dp_inactive_psr);
>> +
>> +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
>> +{
>> +   unsigned char psr_version;
>> +
>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
>> +   dev_info(dp->dev, "Panel PSR version : %x\n", psr_version);
>> +
> This info message is likely to be spammy since it's printed everytime
> the panel toggle on. Perhaps downgrade to debug level.

Okay, done.

>> +   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
>> +}
>> +
>> +static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
> Return type is int, but the function never fails and you don't check
> the return value when calling it. Seems like this should be void.

Done.

>> +{
>> +   unsigned char psr_en;
>> +
>> +   /* Disable psr function */
>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
>> +   psr_en &= ~DP_PSR_ENABLE;
>> +   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>> +
>> +   /* Main-Link transmitter remains active during PSR active states */
>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
>> +   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
> Why read psr_en if you're just going to overwrite it? Perhaps you meant |= 
> here.
>

Yes, it's my mistaken, no need to read the DP_PSR_EN_CFG, just configure 
it directly is enough.

>> +   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>> +
>> +   /* Enable psr function */
>> +   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
>> +   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
>> +DP_PSR_CRC_VERIFICATION;
> Again, no need to read if you're just overwriting.

Yes, ditto

>> +   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
>> +
>> +   analogix_dp_enable_psr_crc(dp);
>> +
>> +   return 0;
>> +}
>> +
>>   static unsigned char analogix_dp_calc_edid_check_sum(unsigned char 
>>

[PATCH v3 2/4] drm/rockchip: add an common abstracted PSR driver

2016-07-08 Thread Yakir Yang
Sean,

On 07/02/2016 02:00 AM, Sean Paul wrote:
> On Fri, Jul 1, 2016 at 5:19 AM, Yakir Yang  wrote:
>> The PSR driver have exported four symbols for specific device driver:
>> - rockchip_drm_psr_register()
>> - rockchip_drm_psr_unregister()
>> - rockchip_drm_psr_enable()
>> - rockchip_drm_psr_disable()
>> - rockchip_drm_psr_flush()
>>
>> Encoder driver should call the register/unregister interfaces to hook
>> itself into common PSR driver, encoder have implement the 'psr_set'
>> callback which use the set PSR state in hardware side.
>>
>> Crtc driver would call the enable/disable interfaces when vblank is
>> enable/disable, after that the common PSR driver would call the encoder
>> registered callback to set the PSR state.
>>
> This feels overly complicated. It seems like you could cut out a bunch
> of code by just coding the psr functions into vop and
> analogix_dp-rockchip. I suppose the only reason to keep it abstracted
> would be if you plan on supporting psr in a different encoder or crtc
> in rockchip, or if you're planning on moving this into drm core.

I split the psr code into a separate driver, cause it seems make things 
more clearly.

'rockchip_drm_vop.c' need to call the PSR enable/disable interfaces, and 
'rockchip_drm_drv.c' need to call the PSR flush interface. If I put the 
whole psr code into analogix_dp-rockchip driver, then the Rockchip drm 
core driver would tie to analogix_dp-rockchip driver very deeply, and 
hard to expand if there are two PSR device in further.

> Perhaps others will disagree with this sentiment and this is the right
> thing to do.
>
>> Fb driver would call the flush interface in 'fb->dirty' callback, this
>> helper function would force all PSR enabled encoders to exit from PSR
>> for 3 seconds.
>>
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v3:
>> - split the psr flow into an common abstracted PSR driver
>> - implement the 'fb->dirty' callback function (Daniel)
>> - avoid to use notify to acqiure for vact event (Daniel)
>> - remove psr_active() callback which introduce in v2
>>
>> Changes in v2: None
>>
>>   drivers/gpu/drm/rockchip/Makefile   |   2 +-
>>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  12 ++
>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 200 
>> 
>>   drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  12 ++
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  24 
>>   5 files changed, 249 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
>>   create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h
>>
>> diff --git a/drivers/gpu/drm/rockchip/Makefile 
>> b/drivers/gpu/drm/rockchip/Makefile
>> index 05d0713..9746365 100644
>> --- a/drivers/gpu/drm/rockchip/Makefile
>> +++ b/drivers/gpu/drm/rockchip/Makefile
>> @@ -3,7 +3,7 @@
>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>
>>   rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
>> -   rockchip_drm_gem.o rockchip_drm_vop.o
>> +   rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
>>   rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>>
>>   obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
>> b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> index 20f12bc..0fec18f 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>> @@ -21,6 +21,7 @@
>>
>>   #include "rockchip_drm_drv.h"
>>   #include "rockchip_drm_gem.h"
>> +#include "rockchip_drm_psr.h"
>>
>>   #define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
>>
>> @@ -66,9 +67,20 @@ static int rockchip_drm_fb_create_handle(struct 
>> drm_framebuffer *fb,
>>   rockchip_fb->obj[0], handle);
>>   }
>>
>> +static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
>> +struct drm_file *file,
>> +unsigned int flags, unsigned int color,
>> +struct drm_clip_rect *clips,
>> +unsigned int num_clips)
>> +{
>> +   rockchip_drm_psr_flush();
>> +   return 0;
>> +}
>> +
>>   static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
>>  .destroy= rockchip_drm_fb_destroy,
>>  .create_h

[PATCH v3 4/6] drm/panel: simple: Add support for Samsung LSN122DL01-C01 2560x1600 panel

2016-07-08 Thread Yakir Yang
Doug,

On 06/14/2016 01:00 AM, Doug Anderson wrote:
> Yakir,
>
> On Sat, Jun 11, 2016 at 7:56 PM, Yakir Yang  wrote:
>> The Samsung LSN122DL01-C01 is an 12.2" 2560x1600 (WQXGA) TFT-LCD panel
>> connected using eDP interfaces.
>>
>> Signed-off-by: Yakir Yang 
>> ---
>> Changes in v3:
>> - Correct the size of panel_desc to active area 262mmx164mm (Emil, Stéphane)
>>
>> Changes in v2: None
>>
>>   drivers/gpu/drm/panel/panel-simple.c | 25 +
>>   1 file changed, 25 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/panel/panel-simple.c 
>> b/drivers/gpu/drm/panel/panel-simple.c
>> index 2d40a21..17cc973 100644
>> --- a/drivers/gpu/drm/panel/panel-simple.c
>> +++ b/drivers/gpu/drm/panel/panel-simple.c
>> @@ -1246,6 +1246,28 @@ static const struct panel_desc qd43003c0_40 = {
>>  .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
>>   };
>>
>> +static const struct drm_display_mode samsung_lsn122dl01_c01_mode = {
>> +   .clock = 271560,
>> +   .hdisplay = 2560,
>> +   .hsync_start = 2560 + 48,
>> +   .hsync_end = 2560 + 48 + 32,
>> +   .htotal = 2560 + 48 + 32 + 80,
>> +   .vdisplay = 1600,
>> +   .vsync_start = 1600 + 2,
>> +   .vsync_end = 1600 + 2 + 5,
>> +   .vtotal = 1600 + 2 + 5 + 57,
>> +   .vrefresh = 60,
>> +};
>> +
>> +static const struct panel_desc samsung_lsn122dl01_c01 = {
>> +   .modes = _lsn122dl01_c01_mode,
>> +   .num_modes = 1,
>> +   .size = {
>> +   .width = 262,
>> +   .height = 164,
> Earlier you said that the active area of this panel was:
>
>> Display area 262.656(H) X 164.16(V) (12.2”diagonal)
> In other panels I looked at the EDID tended to round numbers, not
> truncate them.  For instance the Starry panel that I sent the patch
> for says in the manual "262.7712 (H) x 164.232 (V)" but then the EDID
> says "263 x 164".

Ah, got it, done.

Thanks,
- Yakir

> That would mean your width should be 263 mm, not 262 mm.
>
> -Doug
>
>
>




[GIT PULL] drm/bridge: analogix-dp: misc fixes & add RK3399 eDP support

2016-07-06 Thread Yakir Yang
Hi Dave,

Please consider merging this tag, which contains the v4 misc fixes and 
add RK3399 eDP support patches[0] I sent on 2016-06-29, rebased onto 
v4.7-rc5.

This tag have been reviewed by :
- Tomasz Figa 
- Sean Paul 
- Douglas Anderson 
- Stéphane Marchesin 

And acked by :
- Mark Yao 

Also tested on Exynos platform successfully by :
Javier Martinez Canillas 

Besides I also have set up a tree[1] to verify the eDP function on 
RK3399 EVB board. That tree is based on v4.7-rc5, but need to apply some 
patches to make things work on RK3399 board, like:
- Apply Mark Yao's RK3399 VOP thread
- Apply ShunQian Zheng's RK3399 IOMMU thread
- Directly update the i2c & rk808 driver to our develop branch
- Directly update the dtsi to our develop branch


[0]: https://lkml.org/lkml/2016/6/29/186
[1]: https://github.com/yakir-Yang/linux/tree/test/analogix-dp-20160705

Thanks,
- Yakir


The following changes since commit 
d9c900b0270a18101403cf5e95c1639fccd43a9f:

   drm/rockchip: analogix_dp: split the lcdc select setting into device 
data (2016-07-05 09:16:33 +0800)

are available in the git repository at:

git at github.com:yakir-Yang/linux.git upstream/analogix-dp-20160705

for you to fetch changes up to 4787b4343fef2e3227b0a69934a8f89e53091fb9:

   dt-bindings: analogix_dp: rockchip: correct the wrong compatible name 
(2016-07-05 09:18:32 +0800)

----
Yakir Yang (10):
   drm/bridge: analogix_dp: correct the register bit define error in 
ANALOGIX_DP_PLL_REG_1
   drm/bridge: analogix_dp: some rockchip chips need to flip REF_CLK 
bit setting
   drm/rockchip: analogix_dp: add rk3399 eDP support
   drm/rockchip: analogix_dp: make panel detect to an optional action
   drm/bridge: analogix_dp: passing the connector as an argument in 
.get_modes()
   drm/rockchip: analogix_dp: correct the connector display color 
format and bpc
   drm/rockchip: analogix_dp: update the comments about why need to 
hardcode VOP output mode
   drm/bridge: analogix_dp: fix no drm hpd event when panel plug in
   drm/rockchip: analogix_dp: introduce the pclk for grf
   dt-bindings: analogix_dp: rockchip: correct the wrong compatible 
name

  Documentation/devicetree/bindings/display/bridge/analogix_dp.txt |   1 +
  Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt | 
  9 +-
  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |   2 +-
  drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |   8 ++---
  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c |  12 ---
  drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h |   5 +--
  drivers/gpu/drm/exynos/exynos_dp.c |   4 +--
  drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 127 
+++
  include/drm/bridge/analogix_dp.h |   9 +-
  9 files changed, 122 insertions(+), 55 deletions(-)

-- next part --
An HTML attachment was scrubbed...
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160706/4c92aa6c/attachment-0001.html>


[PATCH v3 4/4] drm/rockchip: analogix_dp: implement PSR function

2016-07-01 Thread Yakir Yang
Alway enable the PSR function for Rockchip analogix_dp driver. If panel
don't support PSR, then the core analogix_dp would ignore this setting.

Signed-off-by: Yakir Yang 
---
Changes in v3:
- split the common psr logic into a seperate driver, make this to a
  simple sub-psr device driver.

Changes in v2:
- remove vblank notify out (Daniel)
- create a psr_active() callback in vop data struct.

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 52 +
 1 file changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index e81e19a..80a60a6 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -32,6 +32,7 @@
 #include 

 #include "rockchip_drm_drv.h"
+#include "rockchip_drm_psr.h"
 #include "rockchip_drm_vop.h"

 #define RK3288_GRF_SOC_CON60x25c
@@ -68,11 +69,53 @@ struct rockchip_dp_device {
struct regmap*grf;
struct reset_control *rst;

+   struct delayed_work  psr_work;
+   unsigned int psr_state;
+
const struct rockchip_dp_chip_data *data;

struct analogix_dp_plat_data plat_data;
 };

+static int analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
+{
+   struct rockchip_dp_device *dp = to_dp(encoder);
+
+   dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
+
+   if (enabled)
+   dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE;
+   else
+   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
+
+   schedule_delayed_work(>psr_work, msecs_to_jiffies(10));
+
+   return 0;
+}
+
+static void analogix_dp_psr_work(struct work_struct *work)
+{
+   struct rockchip_dp_device *dp =
+   container_of(work, typeof(*dp), psr_work.work);
+   struct drm_crtc *crtc = dp->encoder.crtc;
+   int psr_state = dp->psr_state;
+   int vact_end;
+   int ret;
+
+   if (!crtc)
+   return;
+
+   vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + 
crtc->mode.vdisplay;
+
+   ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end, 100);
+   if (ret == 0) {
+   if (psr_state == EDP_VSC_PSR_STATE_ACTIVE)
+   analogix_dp_active_psr(dp->dev);
+   else
+   analogix_dp_inactive_psr(dp->dev);
+   }
+}
+
 static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
 {
reset_control_assert(dp->rst);
@@ -340,12 +383,21 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
dp->plat_data.power_off = rockchip_dp_powerdown;
dp->plat_data.get_modes = rockchip_dp_get_modes;

+   dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
+   INIT_DELAYED_WORK(>psr_work, analogix_dp_psr_work);
+
+   rockchip_drm_psr_register(>encoder, analogix_dp_psr_set);
+
return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
 }

 static void rockchip_dp_unbind(struct device *dev, struct device *master,
   void *data)
 {
+   struct rockchip_dp_device *dp = dev_get_drvdata(dev);
+
+   rockchip_drm_psr_unregister(>encoder);
+
return analogix_dp_unbind(dev, master, data);
 }

-- 
1.9.1




[PATCH v3 3/4] drm/bridge: analogix_dp: add the PSR function support

2016-07-01 Thread Yakir Yang
The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Signed-off-by: Yakir Yang 
---
Changes in v3:
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments

Changes in v2:
- introduce in v2, splite the common Analogix DP changes out

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 64 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  4 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 54 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  | 28 ++
 include/drm/bridge/analogix_dp.h   |  3 +
 5 files changed, 153 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 32715da..b557097 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -97,6 +97,66 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device 
*dp)
return 0;
 }

+int analogix_dp_active_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   analogix_dp_send_psr_spd(dp, EDP_VSC_PSR_STATE_ACTIVE |
+EDP_VSC_PSR_CRC_VALUES_VALID);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_active_psr);
+
+int analogix_dp_inactive_psr(struct device *dev)
+{
+   struct analogix_dp_device *dp = dev_get_drvdata(dev);
+
+   if (!dp->psr_support)
+   return -EINVAL;
+
+   analogix_dp_send_psr_spd(dp, 0);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_inactive_psr);
+
+static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_version;
+
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, _version);
+   dev_info(dp->dev, "Panel PSR version : %x\n", psr_version);
+
+   return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
+}
+
+static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
+{
+   unsigned char psr_en;
+
+   /* Disable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en &= ~DP_PSR_ENABLE;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Main-Link transmitter remains active during PSR active states */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   /* Enable psr function */
+   analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, _en);
+   psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
+DP_PSR_CRC_VERIFICATION;
+   analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+
+   analogix_dp_enable_psr_crc(dp);
+
+   return 0;
+}
+
 static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
 {
int i;
@@ -921,6 +981,10 @@ static void analogix_dp_commit(struct analogix_dp_device 
*dp)

/* Enable video */
analogix_dp_start_video(dp);
+
+   dp->psr_support = analogix_dp_detect_sink_psr(dp);
+   if (dp->psr_support)
+   analogix_dp_enable_sink_psr(dp);
 }

 int analogix_dp_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index b456380..6ca5dde 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -177,6 +177,7 @@ struct analogix_dp_device {
int hpd_gpio;
boolforce_hpd;
unsigned char   edid[EDID_BLOCK_LENGTH * 2];
+   boolpsr_support;

struct analogix_dp_plat_data *plat_data;
 };
@@ -278,4 +279,7 @@ int analogix_dp_is_video_stream_on(struct 
analogix_dp_device *dp);
 void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp);
 void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
+void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
+void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, int db1);
+
 #endif /* _ANALOGIX_DP_CORE_H */
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 48030f0..e8372c7 100644
--- a/drivers/gpu/drm/bridge/analogix/analog

[PATCH v3 2/4] drm/rockchip: add an common abstracted PSR driver

2016-07-01 Thread Yakir Yang
The PSR driver have exported four symbols for specific device driver:
- rockchip_drm_psr_register()
- rockchip_drm_psr_unregister()
- rockchip_drm_psr_enable()
- rockchip_drm_psr_disable()
- rockchip_drm_psr_flush()

Encoder driver should call the register/unregister interfaces to hook
itself into common PSR driver, encoder have implement the 'psr_set'
callback which use the set PSR state in hardware side.

Crtc driver would call the enable/disable interfaces when vblank is
enable/disable, after that the common PSR driver would call the encoder
registered callback to set the PSR state.

Fb driver would call the flush interface in 'fb->dirty' callback, this
helper function would force all PSR enabled encoders to exit from PSR
for 3 seconds.

Signed-off-by: Yakir Yang 
---
Changes in v3:
- split the psr flow into an common abstracted PSR driver
- implement the 'fb->dirty' callback function (Daniel)
- avoid to use notify to acqiure for vact event (Daniel)
- remove psr_active() callback which introduce in v2

Changes in v2: None

 drivers/gpu/drm/rockchip/Makefile   |   2 +-
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  12 ++
 drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 200 
 drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  12 ++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  24 
 5 files changed, 249 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index 05d0713..9746365 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -3,7 +3,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-   rockchip_drm_gem.o rockchip_drm_vop.o
+   rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o

 obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 20f12bc..0fec18f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -21,6 +21,7 @@

 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
+#include "rockchip_drm_psr.h"

 #define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)

@@ -66,9 +67,20 @@ static int rockchip_drm_fb_create_handle(struct 
drm_framebuffer *fb,
 rockchip_fb->obj[0], handle);
 }

+static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
+struct drm_file *file,
+unsigned int flags, unsigned int color,
+struct drm_clip_rect *clips,
+unsigned int num_clips)
+{
+   rockchip_drm_psr_flush();
+   return 0;
+}
+
 static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
.destroy= rockchip_drm_fb_destroy,
.create_handle  = rockchip_drm_fb_create_handle,
+   .dirty  = rockchip_drm_fb_dirty,
 };

 static struct rockchip_drm_fb *
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
new file mode 100644
index 000..c03
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -0,0 +1,200 @@
+#include 
+
+#include "rockchip_drm_psr.h"
+
+#define PSR_FLUSH_TIMEOUT  msecs_to_jiffies(3000) /* 3 seconds */
+
+static LIST_HEAD(psr_list);
+static DEFINE_MUTEX(psr_list_mutex);
+
+enum psr_state {
+   PSR_FLUSH,
+   PSR_ENABLE,
+   PSR_DISABLE,
+};
+
+struct psr_drv {
+   struct list_head list;
+   enum psr_state state;
+   struct mutex state_mutex;
+
+   struct timer_list flush_timer;
+
+   struct drm_encoder *encoder;
+   int (*set)(struct drm_encoder *encoder, bool enable);
+};
+
+static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
+{
+   struct psr_drv *psr;
+
+   mutex_lock(_list_mutex);
+   list_for_each_entry(psr, _list, list) {
+   if (psr->encoder->crtc == crtc) {
+   mutex_unlock(_list_mutex);
+   return psr;
+   }
+   }
+   mutex_unlock(_list_mutex);
+
+   return ERR_PTR(-ENODEV);
+}
+
+static void psr_enable(struct psr_drv *psr)
+{
+   if (psr->state == PSR_ENABLE)
+   return;
+
+   mutex_lock(>state_mutex);
+   psr->state = PSR_ENABLE;
+   psr->set(psr->encoder, true);
+   mutex_unlock(>state_mutex);
+}
+
+static void psr_disable(struct psr_drv *psr)
+{
+   if (psr->state == PSR_DISABLE)
+   return;
+
+   mutex_lock(>state

[PATCH v3 1/4] drm/rockchip: vop: export line flag function

2016-07-01 Thread Yakir Yang
VOP have integrated a hardware counter which indicate the exact display
line that vop is scanning. And if we're interested in a specific line,
we can set the line number to vop line_flag register, and then vop would
generate a line_flag interrupt for it.

For example eDP PSR function is interested in the vertical blanking
period, then driver could set the line number to zero.

This patch have exported a symbol that allow other driver to listen the
line flag event with given timeout limit:
-  rockchip_drm_wait_line_flag()

Signed-off-by: Yakir Yang 
---
Changes in v3:
- Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
- Add 'line_flag_num_0' for RK3288/RK3036
- Remove the notify for waiting line_flag event (Daniel)

Changes in v2:
- Introduce in v2, split VOP line flag changes out

 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 103 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   3 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   4 ++
 4 files changed, 113 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..239b830 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -70,4 +70,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
+int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
+   unsigned int mstimeout);
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index c8a62a8..cd3cac5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -121,6 +121,8 @@ struct vop {
/* protected by dev->event_lock */
struct drm_pending_vblank_event *event;

+   struct completion line_flag_completion;
+
const struct vop_data *data;

uint32_t *regsbak;
@@ -431,6 +433,59 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+/*
+ * (1) each frame starts at the start of the Vsync pulse which is signaled by
+ * the "FRAME_SYNC" interrupt.
+ * (2) the active data region of each frame ends at dsp_vact_end
+ * (3) we should program this same number (dsp_vact_end) into 
dsp_line_frag_num,
+ *  to get "LINE_FLAG" interrupt at the end of the active on screen data.
+ *
+ * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
+ * Interrupts
+ * LINE_FLAG ---+
+ * FRAME_SYNC + |
+ *| |
+ *v v
+ *| Vsync | Vbp |  Vactive  | Vfp |
+ *^ ^   ^ ^
+ *| |   | |
+ *| |   | |
+ * dsp_vs_end + |   | |   VOP_DSP_VTOTAL_VS_END
+ * dsp_vact_start --+   | |   VOP_DSP_VACT_ST_END
+ * dsp_vact_end + |   VOP_DSP_VACT_ST_END
+ * dsp_total -+   VOP_DSP_VTOTAL_VS_END
+ */
+
+static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
+{
+   unsigned long flags;
+
+   if (WARN_ON(!vop->is_enabled))
+   return;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   VOP_CTRL_SET(vop, line_flag_num_0, line_num);
+   VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
+   vop_cfg_done(vop);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+}
+
+static void vop_line_flag_irq_disable(struct vop *vop)
+{
+   unsigned long flags;
+
+   if (WARN_ON(!vop->is_enabled))
+   return;
+
+   spin_lock_irqsave(>irq_lock, flags);
+
+   VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 0);
+
+   spin_unlock_irqrestore(>irq_lock, flags);
+}
+
 static void vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
@@ -1157,6 +1212,13 @@ static irqreturn_t vop_isr(int irq, void *data)
ret = IRQ_HANDLED;
}

+   if (active_irqs & LINE_FLAG_INTR) {
+   if (!completion_done(>line_flag_completion))
+   complete(>line_flag_completion);
+   active_irqs &= ~LINE_FLAG_INTR;
+   ret = IRQ_HANDLED;
+   }
+
if (active_irqs & FS_INTR) {
drm_crtc_handle_vblank(crtc);
vop_handle_vblank(vop);
@@ -1255,6 +1317,7 @@ static int vop_create_crtc(struct vop *vop)

init_completion(>ds

[PATCH v3 0/4] Add PSR function support for Analogix/Rockchip DP

2016-07-01 Thread Yakir Yang
Hi all,

The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make a lots
of sense to save the power consumption.

This v3 version have splited an common PSR driver for Rockchip, which is
biggest changes from v2.

This thread is based on Mark's RK3399 VOP thread[0] and my RK3399 eDP
thread[1].

[0]: https://patchwork.kernel.org/patch/8886041/
[1]: https://patchwork.kernel.org/patch/9204497/

Thanks,
- Yakir


Changes in v3:
- Remove the notify for waiting line_flag event (Daniel)
- implement the 'fb->dirty' callback function (Daniel)
- avoid to use notify to acqiure for vact event (Daniel)
- split the psr flow into an common abstracted PSR driver
- Export the 'rockchip_drm_wait_line_flag' symbol, and document it.
- Add 'line_flag_num_0' for RK3288/RK3036
- remove psr_active() callback which introduce in v2
- split analogix_dp_enable_psr(), make it more clearly
analogix_dp_detect_sink_psr()
analogix_dp_enable_sink_psr()
- remove some nosie register setting comments
- split the common psr logic into a seperate driver, make this to a
  simple sub-psr device driver.

Changes in v2:
- Introduce in v2, split VOP line flag changes out
- introduce in v2, splite the common Analogix DP changes out
- remove vblank notify out (Daniel)
- create a psr_active() callback in vop data struct.

Yakir Yang (4):
  drm/rockchip: vop: export line flag function
  drm/rockchip: add an common abstracted PSR driver
  drm/bridge: analogix_dp: add the PSR function support
  drm/rockchip: analogix_dp: implement PSR function

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  64 +++
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |   4 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  |  54 ++
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  |  28 +++
 drivers/gpu/drm/rockchip/Makefile  |   2 +-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c|  52 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h|   3 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c |  12 ++
 drivers/gpu/drm/rockchip/rockchip_drm_psr.c| 200 +
 drivers/gpu/drm/rockchip/rockchip_drm_psr.h|  12 ++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 127 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h|   3 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c|   4 +
 include/drm/bridge/analogix_dp.h   |   3 +
 14 files changed, 567 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h

-- 
1.9.1




[PATCH v4 0/11] Misc fixup and add RK3399 eDP support to Analogix DP driver[Involving remittance information, please pay attention to the safety of property]

2016-06-30 Thread Yakir Yang
Sean,

On 06/29/2016 10:01 PM, Sean Paul wrote:
> On Wed, Jun 29, 2016 at 5:14 AM, Yakir Yang  wrote:
>> RK3399 and RK3288 shared the same eDP IP controller, only some light
>> difference with VOP configure and GRF configure.
>>
> The whole set looks good to me. All patches should have my R-b now,
> thanks for the update.

Thanks  :-D

- Yakir

> Sean
>
>
>
>> Also same misc fix to analogix_dp driver:
>> - Hotplug invalid which report by Dan Carpenter
>> - Make panel detect to an optional action
>> - correct the register bit define error in ANALOGIX_DP_PLL_REG_1
>>
>> Changes in v4:
>> - Assigned the GRF setting magic numbers to a #define that corresponds to
>>a TRM name. (Sean & Heiko)
>> - Pass the chip type to device type directly. (Sean)
>> - Add reviewed flag from Tomasz.
>> - Add reviewed flag from Sean
>> - Remove subdev_type number, and add 'is_rockchip(type)' helper function 
>> (Sean)
>> - Add reviewed flag from Tomasz.
>> - Improved the overly complicated .atomic_check function. (Sean)
>> - Add reviewed flag from Tomasz
>> - Move of_node_put(panel_node) directly below of_drm_find_panel (Sean)
>> - Add reviewed flag from Tomasz
>> - Add reviewed flag from Sean.
>> - Add reviewed flag from Tomasz.
>> - Using mask variable to collect the YUV video format. (Sean)
>> - Add reviewed flag from Tomasz.
>> - Correct the misspell of 'contoller'. (Sean)
>> - Add reviewed flag from Sean.
>> - Add reviewed flag from Tomasz.
>> - Add reviewed flag from Doug.
>> - Add reviewed flag from Tomasz.
>> - Fix compiled error, sorry.
>>"dp->cgfclk"  -->  'dp->grfclk'
>> - Check the the error code properly, 'EPROBE_DEFER' should be returned,
>>'ENOENT' should assign a NULL point to grfclk, other errors should be
>>regarded as failed. (Tomasz, Doug, reviewed at Google Gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/351821/20/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>>  at 249]
>> - Add the document about optional 'grf' clock (Tomasz, Doug, reviewed at 
>> Google Gerrit)
>>  [https://chromium-review.googlesource.com/#/c/351821/]
>> - Add reviewed flag from Doug.
>> - Add reviewed flag from Tomasz.
>>
>> Changes in v3:
>> - Write a kerneldoc-style comment explaining the chips data fields (Tomasz, 
>> reviewed at Google Gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/346313/10/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>>  at 39]
>> - Drop the '.lcdcsel_mask' number in chips data field (Tomasz, reviewed at 
>> Google Gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/346313/10/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>>  at 382]
>> - Add acked flag from Mark.
>> - Add reviewed flag from Tomasz.
>>  [https://chromium-review.googlesource.com/#/c/346315/15]
>> - Add tested flag from Javier
>> - Make this hack code more clear (Tomasz, reviewed at Google Gerrit)
>>reg = ~reg & REF_CLK_MASK;  --->  reg ^= REF_CLK_MASK;
>>  
>> [https://chromium-review.googlesource.com/#/c/346852/7/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>>  at 80]
>> - Add tested flag from Javier
>> - Give the "rk3399-edp" a separate line for clarity in document (Tomasz, 
>> reviewed at Google Gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/346314/10/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
>>  at 5]
>> - Move 'output_type' setting before the return statement (Tomasz, reviewed 
>> at Google Gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/346314/10/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>>  at 154]
>> - Add the acked flag from Mark.
>> - Add the acked flag from Mark.
>> - Avoid to change any internal driver state in .mode_valid interface. 
>> (Tomasz, reviewed at Google Gerrit)
>>  
>> [https://chromium-review.googlesource.com/#/c/346318/10/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
>>  at 113]
>> - Hook the connector's color_formats in .get_modes directly. (Tomasz, 
>> reviewed at Google Gerrit)
>>  [https://chromium-review.googlesource.com/#/c/346317/15]
>> - Add the acked flag from Mark.
>> - Add the reviewed flag from Tomasz.
>>  [https://chromium-review.googlesource.com/#/c/346853/12]
>> - Add the acked flag from Mark.
>> - Add reviewed flag from Stéphane.
>>  [https://chromium-review.googlesource.com/#/c/346319/15]
>> - Add tested flag from Jav

[PATCH 1/3] drm: bridge: add DesignWare HDMI I2S audio support

2016-06-29 Thread Yakir Yang
> + conf1 = HDMI_AUD_CONF1_WIDTH_16;
> + break;
> + case 24:
> + case 32:
> + conf1 = HDMI_AUD_CONF1_WIDTH_24;
> + break;
> + }
> +
> + dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
> +
> + hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS);
> + hdmi_write(audio, conf0, HDMI_AUD_CONF0);
> + hdmi_write(audio, conf1, HDMI_AUD_CONF1);
> +
> + dw_hdmi_audio_enable(hdmi);
> +
> + return 0;
> +}
> +
> +static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data)
> +{
> + struct dw_hdmi_i2s_audio_data *audio = data;
> + struct dw_hdmi *hdmi = audio->hdmi;
> +
> + dw_hdmi_audio_disable(hdmi);
> +
> + hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0);
> +}
> +
> +static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
> + .hw_params  = dw_hdmi_i2s_hw_params,
> + .audio_shutdown = dw_hdmi_i2s_audio_shutdown,
> +};
> +
> +static int snd_dw_hdmi_probe(struct platform_device *pdev)
> +{
> + struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data;
> + struct platform_device_info pdevinfo;
> + struct hdmi_codec_pdata pdata;
> +
> + pdata.ops   = _hdmi_i2s_ops;
> + pdata.i2s   = 1;
> + pdata.max_i2s_channels  = 6;
> + pdata.data  = audio;
> +
> + memset(, 0, sizeof(pdevinfo));
> + pdevinfo.parent = pdev->dev.parent;
> + pdevinfo.id = PLATFORM_DEVID_AUTO;
> + pdevinfo.name   = HDMI_CODEC_DRV_NAME;
> + pdevinfo.data   = 
> + pdevinfo.size_data  = sizeof(pdata);
> + pdevinfo.dma_mask   = DMA_BIT_MASK(32);
> +
> + return IS_ERR_OR_NULL(platform_device_register_full());
> +}
> +
> +static struct platform_driver snd_dw_hdmi_driver = {
> + .probe  = snd_dw_hdmi_probe,
> + .driver = {
> + .name = DRIVER_NAME,
> + .owner = THIS_MODULE,
> + },
> +};
> +module_platform_driver(snd_dw_hdmi_driver);
> +

I don't think you need a separate driver for dw-hdmi i2s-audio, you can 
just place then into the main dw-hdmi driver (just like dw-hdmi ahb-audio).

And then you don't need to add an external point into hdmi-codec for 
storing the 'struct dw_hdmi_i2s_audio_data'.

Cheers,
- Yakir

> +MODULE_AUTHOR("Kuninori Morimoto ");
> +MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c 
> b/drivers/gpu/drm/bridge/dw-hdmi.c
> index 55e73e8..e9ba59e 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -2013,10 +2013,11 @@ int dw_hdmi_bind(struct device *dev, struct device 
> *master,
>   struct device_node *np = dev->of_node;
>   struct platform_device_info pdevinfo;
>   struct device_node *ddc_node;
> - struct dw_hdmi_audio_data audio;
>   struct dw_hdmi *hdmi;
>   int ret;
>   u32 val = 1;
> + u8 config0;
> + u8 config1;
>   
>   hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
>   if (!hdmi)
> @@ -2185,7 +2186,12 @@ int dw_hdmi_bind(struct device *dev, struct device 
> *master,
>   pdevinfo.parent = dev;
>   pdevinfo.id = PLATFORM_DEVID_AUTO;
>   
> - if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
> + config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
> + config1 = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
> +
> + if (config1 & HDMI_CONFIG1_AHB) {
> + struct dw_hdmi_audio_data audio;
> +
>   audio.phys = iores->start;
>   audio.base = hdmi->regs;
>   audio.irq = irq;
> @@ -2197,6 +2203,18 @@ int dw_hdmi_bind(struct device *dev, struct device 
> *master,
>   pdevinfo.size_data = sizeof(audio);
>   pdevinfo.dma_mask = DMA_BIT_MASK(32);
>   hdmi->audio = platform_device_register_full();
> + } else if (config0 & HDMI_CONFIG0_I2S) {
> + struct dw_hdmi_i2s_audio_data audio;
> +
> + audio.hdmi  = hdmi;
> + audio.write = hdmi_writeb;
> + audio.read  = hdmi_readb;
> +
> + pdevinfo.name = "dw-hdmi-i2s-audio";
> + pdevinfo.data = 
> + pdevinfo.size_data = sizeof(audio);
> + pdevinfo.dma_mask = DMA_BIT_MASK(32);
> + hdmi->audio = platform_device_register_full();
>   }
>   
>   /* Unmute I2CM interrupts and reset HDMI DDC I2C mast

[PATCH v4 11/11] dt-bindings: analogix_dp: rockchip: correct the wrong compatible name

2016-06-29 Thread Yakir Yang
The document about rockchip platform make a mistaken in available
compatible name of "rk3288-edp", we should correct it to "rk3288-dp"
which correspond to the compatible name in driver.

This mistaken was introduced in commit be91c36247089 ("dt-bindings:
add document for rockchip variant of analogix_dp").

Reported-by: Tomasz Figa 
Signed-off-by: Yakir Yang 
Reviewed-by: Douglas Anderson 
Reviewed-by: Tomasz Figa 
---
Changes in v4:
- Add reviewed flag from Doug.
- Add reviewed flag from Tomasz.

Changes in v3:
- Add this patch in v3

 .../devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
index 0b39256..01cced1 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
@@ -2,7 +2,7 @@ Rockchip RK3288 specific extensions to the Analogix Display Port
 

 Required properties:
-- compatible: "rockchip,rk3288-edp",
+- compatible: "rockchip,rk3288-dp",
  "rockchip,rk3399-edp";

 - reg: physical base address of the controller and length
-- 
1.9.1




[PATCH v4 10/11] drm/rockchip: analogix_dp: introduce the pclk for grf

2016-06-29 Thread Yakir Yang
For RK3399's GRF module, if we want to operate the graphic related grf
registers, we need to enable the pclk_vio_grf which supply power for VIO
GRF IOs, so it's better to introduce an optional grf clock in driver.

Signed-off-by: Yakir Yang 
Reviewed-by: Douglas Anderson 
Reviewed-by: Tomasz Figa 
---
Changes in v4:
- Add reviewed flag from Doug.
- Add reviewed flag from Tomasz.
- Fix compiled error, sorry.
  "dp->cgfclk"  -->  'dp->grfclk'
- Check the the error code properly, 'EPROBE_DEFER' should be returned,
  'ENOENT' should assign a NULL point to grfclk, other errors should be
  regarded as failed. (Tomasz, Doug, reviewed at Google Gerrit)

[https://chromium-review.googlesource.com/#/c/351821/20/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 249]
- Add the document about optional 'grf' clock (Tomasz, Doug, reviewed at Google 
Gerrit)
[https://chromium-review.googlesource.com/#/c/351821/]

Changes in v3:
- Add this patch in v3

 .../display/rockchip/analogix_dp-rockchip.txt  |  6 ++
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 23 +++---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
index 726c945..0b39256 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
@@ -28,6 +28,12 @@ Required properties:
 Port 0: contained 2 endpoints, connecting to the output of vop.
 Port 1: contained 1 endpoint, connecting to the input of panel.

+Optional property for different chips:
+- clocks: from common clock binding: handle to grf_vio clock.
+
+- clock-names: from common clock binding:
+  Required elements: "grf"
+
 For the below properties, please refer to Analogix DP binding document:
  * Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
 - phys (required)
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 850edc4..e81e19a 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -64,6 +64,7 @@ struct rockchip_dp_device {
struct drm_display_mode  mode;

struct clk   *pclk;
+   struct clk   *grfclk;
struct regmap*grf;
struct reset_control *rst;

@@ -160,11 +161,17 @@ static void rockchip_dp_drm_encoder_enable(struct 
drm_encoder *encoder)

dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");

-   ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val);
-   if (ret != 0) {
-   dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
+   ret = clk_prepare_enable(dp->grfclk);
+   if (ret < 0) {
+   dev_err(dp->dev, "failed to enable grfclk %d\n", ret);
return;
}
+
+   ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val);
+   if (ret != 0)
+   dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
+
+   clk_disable_unprepare(dp->grfclk);
 }

 static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder)
@@ -234,6 +241,16 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp)
return PTR_ERR(dp->grf);
}

+   dp->grfclk = devm_clk_get(dev, "grf");
+   if (PTR_ERR(dp->grfclk) == -ENOENT) {
+   dp->grfclk = NULL;
+   } else if (PTR_ERR(dp->grfclk) == -EPROBE_DEFER) {
+   return -EPROBE_DEFER;
+   } else if (IS_ERR(dp->grfclk)) {
+   dev_err(dev, "failed to get grf clock\n");
+   return PTR_ERR(dp->grfclk);
+   }
+
dp->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(dp->pclk)) {
dev_err(dev, "failed to get pclk property\n");
-- 
1.9.1




[PATCH v4 09/11] drm/bridge: analogix_dp: fix no drm hpd event when panel plug in

2016-06-29 Thread Yakir Yang
The enum value of DP_IRQ_TYPE_HP_CABLE_IN is zero, but driver only
send drm hp event when the irq_type and the enum value is true.

if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN || ...)
drm_helper_hpd_irq_event(dp->drm_dev);

So there would no drm hpd event when cable plug in, to fix that
just need to assign all hotplug enum with no-zero values.

Reported-by: Dan Carpenter 
Signed-off-by: Yakir Yang 
Reviewed-by: Sean Paul 
Reviewed-by: Stéphane Marchesin 
Reviewed-by: Tomasz Figa 
Tested-by: Javier Martinez Canillas 
---
Changes in v4:
- Add reviewed flag from Sean.
- Add reviewed flag from Tomasz.

Changes in v3:
- Add reviewed flag from Stéphane.
[https://chromium-review.googlesource.com/#/c/346319/15]
- Add tested flag from Javier

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index f09275d..b456380 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -127,10 +127,10 @@ enum analog_power_block {
 };

 enum dp_irq_type {
-   DP_IRQ_TYPE_HP_CABLE_IN,
-   DP_IRQ_TYPE_HP_CABLE_OUT,
-   DP_IRQ_TYPE_HP_CHANGE,
-   DP_IRQ_TYPE_UNKNOWN,
+   DP_IRQ_TYPE_HP_CABLE_IN  = BIT(0),
+   DP_IRQ_TYPE_HP_CABLE_OUT = BIT(1),
+   DP_IRQ_TYPE_HP_CHANGE= BIT(2),
+   DP_IRQ_TYPE_UNKNOWN  = BIT(3),
 };

 struct video_info {
-- 
1.9.1




[PATCH v4 08/11] drm/rockchip: analogix_dp: update the comments about why need to hardcode VOP output mode

2016-06-29 Thread Yakir Yang
The hardware IC designed that VOP must output the RGB10 video format to
eDP contoller, and if eDP panel only support RGB8, then eDP contoller
should cut down the video data, not via VOP contoller, that's why we need
to hardcode the VOP output mode to RGA10 here.

Signed-off-by: Yakir Yang 
Acked-by: Mark Yao 
Reviewed-by: Tomasz Figa 
---
Changes in v4:
- Correct the misspell of 'contoller'. (Sean)

Changes in v3:
- Add the reviewed flag from Tomasz.
[https://chromium-review.googlesource.com/#/c/346853/12]
- Add the acked flag from Mark.

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 16 +---
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 0a0fb3a..850edc4 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -182,17 +182,11 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder 
*encoder,
int ret;

/*
-* FIXME(Yakir): driver should configure the CRTC output video
-* mode with the display information which indicated the monitor
-* support colorimetry.
-*
-* But don't know why the CRTC driver seems could only output the
-* RGBaaa rightly. For example, if connect the "innolux,n116bge"
-* eDP screen, EDID would indicated that screen only accepted the
-* 6bpc mode. But if I configure CRTC to RGB666 output, then eDP
-* screen would show a blue picture (RGB888 show a green picture).
-* But if I configure CTRC to RGBaaa, and eDP driver still keep
-* RGB666 input video mode, then screen would works prefect.
+* The hardware IC designed that VOP must output the RGB10 video
+* format to eDP controller, and if eDP panel only support RGB8,
+* then eDP controller should cut down the video data, not via VOP
+* controller, that's why we need to hardcode the VOP output mode
+* to RGA10 here.
 */

s->output_mode = ROCKCHIP_OUT_MODE_;
-- 
1.9.1




[PATCH v4 07/11] drm/rockchip: analogix_dp: correct the connector display color format and bpc

2016-06-29 Thread Yakir Yang
Rockchip VOP couldn't output YUV video format for eDP controller, so
when driver detect connector support YUV video format, we need to hack
it down to RGB888.

Signed-off-by: Yakir Yang 
Acked-by: Mark Yao 
Reviewed-by: Tomasz Figa 
---
Changes in v4:
- Using mask variable to collect the YUV video format. (Sean)
- Add reviewed flag from Tomasz.

Changes in v3:
- Hook the connector's color_formats in .get_modes directly. (Tomasz, reviewed 
at Google Gerrit)
[https://chromium-review.googlesource.com/#/c/346317/15]
- Add the acked flag from Mark.

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 0755573..0a0fb3a 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -110,6 +110,23 @@ static int rockchip_dp_powerdown(struct 
analogix_dp_plat_data *plat_data)
return 0;
 }

+static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data,
+struct drm_connector *connector)
+{
+   struct drm_display_info *di = >display_info;
+   /* VOP couldn't output YUV video format for eDP rightly */
+   u32 mask = DRM_COLOR_FORMAT_YCRCB444 | DRM_COLOR_FORMAT_YCRCB422;
+
+   if ((di->color_formats & mask)) {
+   DRM_DEBUG_KMS("Swapping display color format from YUV to 
RGB\n");
+   di->color_formats &= ~mask;
+   di->color_formats |= DRM_COLOR_FORMAT_RGB444;
+   di->bpc = 8;
+   }
+
+   return 0;
+}
+
 static bool
 rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder,
   const struct drm_display_mode *mode,
@@ -310,6 +327,7 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
dp->plat_data.dev_type = dp->data->chip_type;
dp->plat_data.power_on = rockchip_dp_poweron;
dp->plat_data.power_off = rockchip_dp_powerdown;
+   dp->plat_data.get_modes = rockchip_dp_get_modes;

return analogix_dp_bind(dev, dp->drm_dev, >plat_data);
 }
-- 
1.9.1




[PATCH v4 06/11] drm/bridge: analogix_dp: passing the connector as an argument in .get_modes()

2016-06-29 Thread Yakir Yang
It's better to pass the connector to platform driver in .get_modes()
callback, just like what the .get_modes() helper function designed.

Signed-off-by: Yakir Yang 
Reviewed-by: Sean Paul 
Reviewed-by: Tomasz Figa 
---
Changes in v4:
- Add reviewed flag from Sean.
- Add reviewed flag from Tomasz.

Changes in v3:
- Avoid to change any internal driver state in .mode_valid interface. (Tomasz, 
reviewed at Google Gerrit)

[https://chromium-review.googlesource.com/#/c/346318/10/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 113]

 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 +-
 drivers/gpu/drm/exynos/exynos_dp.c | 4 ++--
 include/drm/bridge/analogix_dp.h   | 3 ++-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 7699597..a5e5ae4 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -938,7 +938,7 @@ int analogix_dp_get_modes(struct drm_connector *connector)
num_modes += drm_panel_get_modes(dp->plat_data->panel);

if (dp->plat_data->get_modes)
-   num_modes += dp->plat_data->get_modes(dp->plat_data);
+   num_modes += dp->plat_data->get_modes(dp->plat_data, connector);

return num_modes;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c 
b/drivers/gpu/drm/exynos/exynos_dp.c
index 468498e..8a555ed 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -67,10 +67,10 @@ static int exynos_dp_poweroff(struct analogix_dp_plat_data 
*plat_data)
return exynos_dp_crtc_clock_enable(plat_data, false);
 }

-static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data)
+static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data,
+  struct drm_connector *connector)
 {
struct exynos_dp_device *dp = to_dp(plat_data);
-   struct drm_connector *connector = >connector;
struct drm_display_mode *mode;
int num_modes = 0;

diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h
index fc4aea3..261b86d 100644
--- a/include/drm/bridge/analogix_dp.h
+++ b/include/drm/bridge/analogix_dp.h
@@ -34,7 +34,8 @@ struct analogix_dp_plat_data {
int (*power_off)(struct analogix_dp_plat_data *);
int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *,
  struct drm_connector *);
-   int (*get_modes)(struct analogix_dp_plat_data *);
+   int (*get_modes)(struct analogix_dp_plat_data *,
+struct drm_connector *);
 };

 int analogix_dp_resume(struct device *dev);
-- 
1.9.1




[PATCH v4 05/11] drm/rockchip: analogix_dp: make panel detect to an optional action

2016-06-29 Thread Yakir Yang
Some boards don't need to declare a panel device node, like the
display interface is DP monitors, so it's necessary to make the
panel detect to an optional action.

Signed-off-by: Yakir Yang 
Acked-by: Mark Yao 
Reviewed-by: Tomasz Figa 
---
Changes in v4:
- Move of_node_put(panel_node) directly below of_drm_find_panel (Sean)
- Add reviewed flag from Tomasz

Changes in v3:
- Add the acked flag from Mark.

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 47 +++--
 1 file changed, 21 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 8557a08..0755573 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -329,38 +329,33 @@ static int rockchip_dp_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
struct device_node *panel_node, *port, *endpoint;
+   struct drm_panel *panel = NULL;
struct rockchip_dp_device *dp;
-   struct drm_panel *panel;

port = of_graph_get_port_by_id(dev->of_node, 1);
-   if (!port) {
-   dev_err(dev, "can't find output port\n");
-   return -EINVAL;
-   }
-
-   endpoint = of_get_child_by_name(port, "endpoint");
-   of_node_put(port);
-   if (!endpoint) {
-   dev_err(dev, "no output endpoint found\n");
-   return -EINVAL;
-   }
-
-   panel_node = of_graph_get_remote_port_parent(endpoint);
-   of_node_put(endpoint);
-   if (!panel_node) {
-   dev_err(dev, "no output node found\n");
-   return -EINVAL;
-   }
-
-   panel = of_drm_find_panel(panel_node);
-   if (!panel) {
-   DRM_ERROR("failed to find panel\n");
+   if (port) {
+   endpoint = of_get_child_by_name(port, "endpoint");
+   of_node_put(port);
+   if (!endpoint) {
+   dev_err(dev, "no output endpoint found\n");
+   return -EINVAL;
+   }
+
+   panel_node = of_graph_get_remote_port_parent(endpoint);
+   of_node_put(endpoint);
+   if (!panel_node) {
+   dev_err(dev, "no output node found\n");
+   return -EINVAL;
+   }
+
+   panel = of_drm_find_panel(panel_node);
of_node_put(panel_node);
-   return -EPROBE_DEFER;
+   if (!panel) {
+   DRM_ERROR("failed to find panel\n");
+   return -EPROBE_DEFER;
+   }
}

-   of_node_put(panel_node);
-
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
if (!dp)
return -ENOMEM;
-- 
1.9.1




[PATCH v4 04/11] drm/rockchip: analogix_dp: add rk3399 eDP support

2016-06-29 Thread Yakir Yang
RK3399 and RK3288 shared the same eDP IP controller, only some light
difference with VOP configure and GRF configure.

Signed-off-by: Yakir Yang 
Acked-by: Mark Yao 
Reviewed-by: Tomasz Figa 
---
Changes in v4:
- Improved the overly complicated .atomic_check function. (Sean)
- Add reviewed flag from Tomasz

Changes in v3:
- Give the "rk3399-edp" a separate line for clarity in document (Tomasz, 
reviewed at Google Gerrit)

[https://chromium-review.googlesource.com/#/c/346314/10/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
 at 5]
- Move 'output_type' setting before the return statement (Tomasz, reviewed at 
Google Gerrit)

[https://chromium-review.googlesource.com/#/c/346314/10/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 154]
- Add the acked flag from Mark.

 .../bindings/display/bridge/analogix_dp.txt|  1 +
 .../display/rockchip/analogix_dp-rockchip.txt  |  3 ++-
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 23 ++
 include/drm/bridge/analogix_dp.h   |  3 ++-
 4 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt 
b/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
index 4f2ba8c..4a0f4f7 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
+++ b/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
@@ -5,6 +5,7 @@ Required properties for dp-controller:
platform specific such as:
 * "samsung,exynos5-dp"
 * "rockchip,rk3288-dp"
+* "rockchip,rk3399-edp"
-reg:
physical base address of the controller and length
of memory mapped region.
diff --git 
a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt 
b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
index e832ff9..726c945 100644
--- 
a/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
+++ 
b/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
@@ -2,7 +2,8 @@ Rockchip RK3288 specific extensions to the Analogix Display Port
 

 Required properties:
-- compatible: "rockchip,rk3288-edp";
+- compatible: "rockchip,rk3288-edp",
+ "rockchip,rk3399-edp";

 - reg: physical base address of the controller and length

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 0a30931..8557a08 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -36,6 +36,8 @@

 #define RK3288_GRF_SOC_CON60x25c
 #define RK3288_EDP_LCDC_SELBIT(5)
+#define RK3399_GRF_SOC_CON20   0x6250
+#define RK3399_EDP_LCDC_SELBIT(5)

 #define HIWORD_UPDATE(val, mask)   (val | (mask) << 16)

@@ -159,6 +161,8 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder 
*encoder,
  struct drm_connector_state *conn_state)
 {
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+   struct rockchip_dp_device *dp = to_dp(encoder);
+   int ret;

/*
 * FIXME(Yakir): driver should configure the CRTC output video
@@ -173,8 +177,19 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder 
*encoder,
 * But if I configure CTRC to RGBaaa, and eDP driver still keep
 * RGB666 input video mode, then screen would works prefect.
 */
+
s->output_mode = ROCKCHIP_OUT_MODE_;
s->output_type = DRM_MODE_CONNECTOR_eDP;
+   if (dp->data->chip_type == RK3399_EDP) {
+   /*
+* For RK3399, VOP Lit must code the out mode to RGB888,
+* VOP Big must code the out mode to RGB10.
+*/
+   ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node,
+   encoder);
+   if (ret > 0)
+   s->output_mode = ROCKCHIP_OUT_MODE_P888;
+   }

return 0;
 }
@@ -378,6 +393,13 @@ static const struct dev_pm_ops rockchip_dp_pm_ops = {
 #endif
 };

+static const struct rockchip_dp_chip_data rk3399_edp = {
+   .lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
+   .lcdsel_big = HIWORD_UPDATE(0, RK3399_EDP_LCDC_SEL),
+   .lcdsel_lit = HIWORD_UPDATE(RK3399_EDP_LCDC_SEL, RK3399_EDP_LCDC_SEL),
+   .chip_type = RK3399_EDP,
+};
+
 static const struct rockchip_dp_chip_data rk3288_dp = {
.lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
.lcdsel_big = HIWORD_UPDATE(0, RK3288_EDP_LCDC_SEL),
@@ -387,6 +409,7 @@ static const struct rockchip_dp_chip_data rk3288_dp = {

 static const struct of_device_id rockchip_dp_dt_ids[] = {
{.c

[PATCH v4 03/11] drm/bridge: analogix_dp: some rockchip chips need to flip REF_CLK bit setting

2016-06-29 Thread Yakir Yang
As vendor document indicate, when REF_CLK bit set 0, then DP
phy's REF_CLK should switch to 24M source clock.

But due to IC PHY layout mistaken, some chips need to flip this
bit(like RK3288), and unfortunately they didn't indicate in the
DP version register. That's why we have to make this little hack.

Signed-off-by: Yakir Yang 
Reviewed-by: Tomasz Figa 
Tested-by: Javier Martinez Canillas 
---
Changes in v4:
- Remove subdev_type number, and add 'is_rockchip(type)' helper function (Sean)
- Add reviewed flag from Tomasz.

Changes in v3:
- Make this hack code more clear (Tomasz, reviewed at Google Gerrit)
  reg = ~reg & REF_CLK_MASK;  --->  reg ^= REF_CLK_MASK;

[https://chromium-review.googlesource.com/#/c/346852/7/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
 at 80]
- Add tested flag from Javier

 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 12 
 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h |  1 +
 include/drm/bridge/analogix_dp.h  |  5 +
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 49205ef..48030f0 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -74,8 +74,12 @@ void analogix_dp_init_analog_param(struct analogix_dp_device 
*dp)
reg = SEL_24M | TX_DVDD_BIT_1_0625V;
writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2);

-   if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) {
-   writel(REF_CLK_24M, dp->reg_base + ANALOGIX_DP_PLL_REG_1);
+   if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {
+   reg = REF_CLK_24M;
+   if (dp->plat_data->dev_type == RK3288_DP)
+   reg ^= REF_CLK_MASK;
+
+   writel(reg, dp->reg_base + ANALOGIX_DP_PLL_REG_1);
writel(0x95, dp->reg_base + ANALOGIX_DP_PLL_REG_2);
writel(0x40, dp->reg_base + ANALOGIX_DP_PLL_REG_3);
writel(0x58, dp->reg_base + ANALOGIX_DP_PLL_REG_4);
@@ -244,7 +248,7 @@ void analogix_dp_set_analog_power_down(struct 
analogix_dp_device *dp,
u32 reg;
u32 phy_pd_addr = ANALOGIX_DP_PHY_PD;

-   if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP))
+   if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
phy_pd_addr = ANALOGIX_DP_PD;

switch (block) {
@@ -448,7 +452,7 @@ void analogix_dp_init_aux(struct analogix_dp_device *dp)
analogix_dp_reset_aux(dp);

/* Disable AUX transaction H/W retry */
-   if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP))
+   if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))
reg = AUX_BIT_PERIOD_EXPECTED_DELAY(0) |
  AUX_HW_RETRY_COUNT_SEL(3) |
  AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
index 88d56ad..cdcc6c5 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
@@ -165,6 +165,7 @@
 /* ANALOGIX_DP_PLL_REG_1 */
 #define REF_CLK_24M(0x1 << 0)
 #define REF_CLK_27M(0x0 << 0)
+#define REF_CLK_MASK   (0x1 << 0)

 /* ANALOGIX_DP_LANE_MAP */
 #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6)
diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h
index 25afb31..790ab5d 100644
--- a/include/drm/bridge/analogix_dp.h
+++ b/include/drm/bridge/analogix_dp.h
@@ -18,6 +18,11 @@ enum analogix_dp_devtype {
RK3288_DP,
 };

+static inline bool is_rockchip(enum analogix_dp_devtype type)
+{
+   return type == RK3288_DP;
+}
+
 struct analogix_dp_plat_data {
enum analogix_dp_devtype dev_type;
struct drm_panel *panel;
-- 
1.9.1




[PATCH v4 02/11] drm/bridge: analogix_dp: correct the register bit define error in ANALOGIX_DP_PLL_REG_1

2016-06-29 Thread Yakir Yang
There're an register define error in ANALOGIX_DP_PLL_REG_1 which introduced
by commit bcec20fd5ad6 ("drm: bridge: analogix/dp: add some rk3288 special
registers setting").

The PHY PLL input clock source is selected by ANALOGIX_DP_PLL_REG_1
BIT 0, not BIT 1.

Signed-off-by: Yakir Yang 
Reviewed-by: Sean Paul 
Reviewed-by: Tomasz Figa 
Tested-by: Javier Martinez Canillas 
---
Changes in v4:
- Add reviewed flag from Sean

Changes in v3:
- Add reviewed flag from Tomasz.
[https://chromium-review.googlesource.com/#/c/346315/15]
- Add tested flag from Javier

 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h 
b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
index 337912b..88d56ad 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
@@ -163,8 +163,8 @@
 #define HSYNC_POLARITY_CFG (0x1 << 0)

 /* ANALOGIX_DP_PLL_REG_1 */
-#define REF_CLK_24M(0x1 << 1)
-#define REF_CLK_27M(0x0 << 1)
+#define REF_CLK_24M(0x1 << 0)
+#define REF_CLK_27M(0x0 << 0)

 /* ANALOGIX_DP_LANE_MAP */
 #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6)
-- 
1.9.1




[PATCH v4 01/11] drm/rockchip: analogix_dp: split the lcdc select setting into device data

2016-06-29 Thread Yakir Yang
eDP controller need to declare which vop provide the video source,
and it's defined in GRF registers.

But different chips have different GRF register address, so we need to
create a device data to declare the GRF messages for each chips.

Signed-off-by: Yakir Yang 
Acked-by: Mark Yao 
Reviewed-by: Tomasz Figa 
---
Changes in v4:
- Assigned the GRF setting magic numbers to a #define that corresponds to
  a TRM name. (Sean & Heiko)
- Pass the chip type to device type directly. (Sean)
- Add reviewed flag from Tomasz.

Changes in v3:
- Write a kerneldoc-style comment explaining the chips data fields (Tomasz, 
reviewed at Google Gerrit)

[https://chromium-review.googlesource.com/#/c/346313/10/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 39]
- Drop the '.lcdcsel_mask' number in chips data field (Tomasz, reviewed at 
Google Gerrit)

[https://chromium-review.googlesource.com/#/c/346313/10/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
 at 382]
- Add acked flag from Mark.

 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 49 -
 1 file changed, 39 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c 
b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index c120172..0a30931 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -14,6 +14,7 @@

 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,13 +34,26 @@
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_vop.h"

+#define RK3288_GRF_SOC_CON60x25c
+#define RK3288_EDP_LCDC_SELBIT(5)
+
+#define HIWORD_UPDATE(val, mask)   (val | (mask) << 16)
+
 #define to_dp(nm)  container_of(nm, struct rockchip_dp_device, nm)

-/* dp grf register offset */
-#define GRF_SOC_CON60x025c
-#define GRF_EDP_LCD_SEL_MASKBIT(5)
-#define GRF_EDP_SEL_VOP_LIT BIT(5)
-#define GRF_EDP_SEL_VOP_BIG 0
+/**
+ * struct rockchip_dp_chip_data - splite the grf setting of kind of chips
+ * @lcdsel_grf_reg: grf register offset of lcdc select
+ * @lcdsel_big: reg value of selecting vop big for eDP
+ * @lcdsel_lit: reg value of selecting vop little for eDP
+ * @chip_type: specific chip type
+ */
+struct rockchip_dp_chip_data {
+   u32 lcdsel_grf_reg;
+   u32 lcdsel_big;
+   u32 lcdsel_lit;
+   u32 chip_type;
+};

 struct rockchip_dp_device {
struct drm_device*drm_dev;
@@ -51,6 +65,8 @@ struct rockchip_dp_device {
struct regmap*grf;
struct reset_control *rst;

+   const struct rockchip_dp_chip_data *data;
+
struct analogix_dp_plat_data plat_data;
 };

@@ -119,13 +135,13 @@ static void rockchip_dp_drm_encoder_enable(struct 
drm_encoder *encoder)
return;

if (ret)
-   val = GRF_EDP_SEL_VOP_LIT | (GRF_EDP_LCD_SEL_MASK << 16);
+   val = dp->data->lcdsel_lit;
else
-   val = GRF_EDP_SEL_VOP_BIG | (GRF_EDP_LCD_SEL_MASK << 16);
+   val = dp->data->lcdsel_big;

dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");

-   ret = regmap_write(dp->grf, GRF_SOC_CON6, val);
+   ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val);
if (ret != 0) {
dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
return;
@@ -246,6 +262,7 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
void *data)
 {
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
+   const struct rockchip_dp_chip_data *dp_data;
struct drm_device *drm_dev = data;
int ret;

@@ -256,10 +273,15 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,
 */
dev_set_drvdata(dev, NULL);

+   dp_data = of_device_get_match_data(dev);
+   if (!dp_data)
+   return -ENODEV;
+
ret = rockchip_dp_init(dp);
if (ret < 0)
return ret;

+   dp->data = dp_data;
dp->drm_dev = drm_dev;

ret = rockchip_dp_drm_create_encoder(dp);
@@ -270,7 +292,7 @@ static int rockchip_dp_bind(struct device *dev, struct 
device *master,

dp->plat_data.encoder = >encoder;

-   dp->plat_data.dev_type = RK3288_DP;
+   dp->plat_data.dev_type = dp->data->chip_type;
dp->plat_data.power_on = rockchip_dp_poweron;
dp->plat_data.power_off = rockchip_dp_powerdown;

@@ -356,8 +378,15 @@ static const struct dev_pm_ops rockchip_dp_pm_ops = {
 #endif
 };

+static const struct rockchip_dp_chip_data rk3288_dp = {
+   .lcdsel_grf_reg = RK3288_GRF_SOC_CON6,
+   .lcdsel_big = HIWORD_UPDATE(0, RK3288_EDP_LCDC_SEL),
+

  1   2   3   4   5   6   7   8   >