Re: [Freedreno] [v3 1/5] drm/msm/dp: Add basic PSR support for eDP

2022-06-29 Thread Sankeerth Billakanti (QUIC)
Hi Dmitry,

>On 21/06/2022 13:53, Vinod Polimera wrote:
>> Add support for basic panel self refresh (PSR) feature for eDP.
>> Add a new interface to set PSR state in the sink from DPU.
>> Program the eDP controller to issue PSR enter and exit SDP to the
>> sink.
>>
>> Signed-off-by: Sankeerth Billakanti 
>> Signed-off-by: Vinod Polimera 
>> ---
>>   drivers/gpu/drm/msm/dp/dp_catalog.c |  81 ++
>>   drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
>>   drivers/gpu/drm/msm/dp/dp_ctrl.c|  76 -
>>   drivers/gpu/drm/msm/dp/dp_ctrl.h|   3 +
>>   drivers/gpu/drm/msm/dp/dp_display.c |  14 +++
>>   drivers/gpu/drm/msm/dp/dp_display.h |   2 +
>>   drivers/gpu/drm/msm/dp/dp_drm.c | 166
>+++-
>>   drivers/gpu/drm/msm/dp/dp_link.c|  36 
>>   drivers/gpu/drm/msm/dp/dp_panel.c   |  22 +
>>   drivers/gpu/drm/msm/dp/dp_panel.h   |   6 ++
>>   drivers/gpu/drm/msm/dp/dp_reg.h |  27 ++
>>   11 files changed, 433 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c
>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> index 7257515..b9021ed 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> @@ -47,6 +47,14 @@
>>   #define DP_INTERRUPT_STATUS2_MASK \
>>  (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)
>>
>> +#define DP_INTERRUPT_STATUS4 \
>> +(PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \
>> +PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT)
>> +
>> +#define DP_INTERRUPT_MASK4 \
>> +(PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
>> +PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)
>> +
>>   struct dp_catalog_private {
>>  struct device *dev;
>>  struct drm_device *drm_dev;
>> @@ -359,6 +367,24 @@ void dp_catalog_ctrl_lane_mapping(struct
>dp_catalog *dp_catalog)
>>  ln_mapping);
>>   }
>>
>> +void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog,
>> +bool enable)
>> +{
>> +u32 val;
>> +struct dp_catalog_private *catalog = container_of(dp_catalog,
>> +struct dp_catalog_private, dp_catalog);
>> +
>> +val = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
>> +val &= ~DP_MAINLINK_CTRL_ENABLE;
>> +
>> +if (enable)
>> +val |= DP_MAINLINK_CTRL_ENABLE;
>> +else
>> +val &= ~DP_MAINLINK_CTRL_ENABLE;
>> +
>> +dp_write_link(catalog, REG_DP_MAINLINK_CTRL, val); }
>> +
>>   void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
>>  bool enable)
>>   {
>> @@ -610,6 +636,47 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog
>*dp_catalog)
>>  dp_write_aux(catalog, REG_DP_DP_HPD_CTRL,
>DP_DP_HPD_CTRL_HPD_EN);
>>   }
>>
>> +static void dp_catalog_enable_sdp(struct dp_catalog_private *catalog)
>> +{
>> +/* trigger sdp */
>> +dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP);
>> +dp_write_link(catalog, MMSS_DP_SDP_CFG3, !UPDATE_SDP); }
>> +
>> +void dp_catalog_ctrl_config_psr(struct dp_catalog *dp_catalog) {
>> +struct dp_catalog_private *catalog = container_of(dp_catalog,
>> +struct dp_catalog_private, dp_catalog);
>> +u32 config;
>> +
>> +/* enable PSR1 function */
>> +config = dp_read_link(catalog, REG_PSR_CONFIG);
>> +config |= PSR1_SUPPORTED;
>> +dp_write_link(catalog, REG_PSR_CONFIG, config);
>> +
>> +dp_write_ahb(catalog, REG_DP_INTR_MASK4,
>DP_INTERRUPT_MASK4);
>> +dp_catalog_enable_sdp(catalog);
>> +}
>> +
>> +void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool
>> +enter) {
>> +struct dp_catalog_private *catalog = container_of(dp_catalog,
>> +struct dp_catalog_private, dp_catalog);
>> +u32 cmd;
>> +
>> +cmd = dp_read_link(catalog, REG_PSR_CMD);
>> +
>> +cmd &= ~(PSR_ENTER | PSR_EXIT);
>> +
>> +if (enter)
>> +cmd |= PSR_ENTER;
>> +else
>> +cmd |= PSR_EXIT;
>> +
>> +dp_catalog_enable_sdp(catalog);
>> +dp_write_link(catalog, REG_PSR_CMD, cmd); }
>> +
>>   u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
>>   {
>>  struct dp_catalog_private *catalog = container_of(dp_catalog, @@
>> -645,6 +712,20 @@ u32 dp_catalog_hpd_get_intr_status(struct dp_catalog
>*dp_catalog)
>>  return isr & (mask | ~DP_DP_HPD_INT_MASK);
>>   }
>>
>> +int dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog
>> +*dp_catalog) {
>> +struct dp_catalog_private *catalog = container_of(dp_catalog,
>> +struct dp_catalog_private, dp_catalog);
>> +u32 intr, intr_ack;
>> +
>> +intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS4);
>> +intr_ack = (intr & DP_INTERRUPT_STATUS4)
>> +<< DP_INTERRUPT_STATUS_ACK_SHIFT;
>> +dp_write_ahb(catalog, REG_DP_INTR_STATUS4, intr_ack);
>> +
>> +return intr;
>> +}
>> +
>>   

Re: [Freedreno] [v3 1/5] drm/msm/dp: Add basic PSR support for eDP

2022-06-21 Thread Dmitry Baryshkov

On 21/06/2022 13:53, Vinod Polimera wrote:

Add support for basic panel self refresh (PSR) feature for eDP.
Add a new interface to set PSR state in the sink from DPU.
Program the eDP controller to issue PSR enter and exit SDP to
the sink.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
---
  drivers/gpu/drm/msm/dp/dp_catalog.c |  81 ++
  drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
  drivers/gpu/drm/msm/dp/dp_ctrl.c|  76 -
  drivers/gpu/drm/msm/dp/dp_ctrl.h|   3 +
  drivers/gpu/drm/msm/dp/dp_display.c |  14 +++
  drivers/gpu/drm/msm/dp/dp_display.h |   2 +
  drivers/gpu/drm/msm/dp/dp_drm.c | 166 +++-
  drivers/gpu/drm/msm/dp/dp_link.c|  36 
  drivers/gpu/drm/msm/dp/dp_panel.c   |  22 +
  drivers/gpu/drm/msm/dp/dp_panel.h   |   6 ++
  drivers/gpu/drm/msm/dp/dp_reg.h |  27 ++
  11 files changed, 433 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 7257515..b9021ed 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -47,6 +47,14 @@
  #define DP_INTERRUPT_STATUS2_MASK \
(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)
  
+#define DP_INTERRUPT_STATUS4 \

+   (PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \
+   PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT)
+
+#define DP_INTERRUPT_MASK4 \
+   (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
+   PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)
+
  struct dp_catalog_private {
struct device *dev;
struct drm_device *drm_dev;
@@ -359,6 +367,24 @@ void dp_catalog_ctrl_lane_mapping(struct dp_catalog 
*dp_catalog)
ln_mapping);
  }
  
+void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog,

+   bool enable)
+{
+   u32 val;
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+
+   val = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+   val &= ~DP_MAINLINK_CTRL_ENABLE;
+
+   if (enable)
+   val |= DP_MAINLINK_CTRL_ENABLE;
+   else
+   val &= ~DP_MAINLINK_CTRL_ENABLE;
+
+   dp_write_link(catalog, REG_DP_MAINLINK_CTRL, val);
+}
+
  void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
bool enable)
  {
@@ -610,6 +636,47 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog 
*dp_catalog)
dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN);
  }
  
+static void dp_catalog_enable_sdp(struct dp_catalog_private *catalog)

+{
+   /* trigger sdp */
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP);
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, !UPDATE_SDP);
+}
+
+void dp_catalog_ctrl_config_psr(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 config;
+
+   /* enable PSR1 function */
+   config = dp_read_link(catalog, REG_PSR_CONFIG);
+   config |= PSR1_SUPPORTED;
+   dp_write_link(catalog, REG_PSR_CONFIG, config);
+
+   dp_write_ahb(catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
+   dp_catalog_enable_sdp(catalog);
+}
+
+void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool enter)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 cmd;
+
+   cmd = dp_read_link(catalog, REG_PSR_CMD);
+
+   cmd &= ~(PSR_ENTER | PSR_EXIT);
+
+   if (enter)
+   cmd |= PSR_ENTER;
+   else
+   cmd |= PSR_EXIT;
+
+   dp_catalog_enable_sdp(catalog);
+   dp_write_link(catalog, REG_PSR_CMD, cmd);
+}
+
  u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
  {
struct dp_catalog_private *catalog = container_of(dp_catalog,
@@ -645,6 +712,20 @@ u32 dp_catalog_hpd_get_intr_status(struct dp_catalog 
*dp_catalog)
return isr & (mask | ~DP_DP_HPD_INT_MASK);
  }
  
+int dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog *dp_catalog)

+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 intr, intr_ack;
+
+   intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS4);
+   intr_ack = (intr & DP_INTERRUPT_STATUS4)
+   << DP_INTERRUPT_STATUS_ACK_SHIFT;
+   dp_write_ahb(catalog, REG_DP_INTR_STATUS4, intr_ack);
+
+   return intr;
+}
+
  int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog)
  {
struct dp_catalog_private *catalog = container_of(dp_catalog,
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 

[Freedreno] [v3 1/5] drm/msm/dp: Add basic PSR support for eDP

2022-06-21 Thread Vinod Polimera
Add support for basic panel self refresh (PSR) feature for eDP.
Add a new interface to set PSR state in the sink from DPU.
Program the eDP controller to issue PSR enter and exit SDP to
the sink.

Signed-off-by: Sankeerth Billakanti 
Signed-off-by: Vinod Polimera 
---
 drivers/gpu/drm/msm/dp/dp_catalog.c |  81 ++
 drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
 drivers/gpu/drm/msm/dp/dp_ctrl.c|  76 -
 drivers/gpu/drm/msm/dp/dp_ctrl.h|   3 +
 drivers/gpu/drm/msm/dp/dp_display.c |  14 +++
 drivers/gpu/drm/msm/dp/dp_display.h |   2 +
 drivers/gpu/drm/msm/dp/dp_drm.c | 166 +++-
 drivers/gpu/drm/msm/dp/dp_link.c|  36 
 drivers/gpu/drm/msm/dp/dp_panel.c   |  22 +
 drivers/gpu/drm/msm/dp/dp_panel.h   |   6 ++
 drivers/gpu/drm/msm/dp/dp_reg.h |  27 ++
 11 files changed, 433 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 7257515..b9021ed 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -47,6 +47,14 @@
 #define DP_INTERRUPT_STATUS2_MASK \
(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)
 
+#define DP_INTERRUPT_STATUS4 \
+   (PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \
+   PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT)
+
+#define DP_INTERRUPT_MASK4 \
+   (PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
+   PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)
+
 struct dp_catalog_private {
struct device *dev;
struct drm_device *drm_dev;
@@ -359,6 +367,24 @@ void dp_catalog_ctrl_lane_mapping(struct dp_catalog 
*dp_catalog)
ln_mapping);
 }
 
+void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog,
+   bool enable)
+{
+   u32 val;
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+
+   val = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+   val &= ~DP_MAINLINK_CTRL_ENABLE;
+
+   if (enable)
+   val |= DP_MAINLINK_CTRL_ENABLE;
+   else
+   val &= ~DP_MAINLINK_CTRL_ENABLE;
+
+   dp_write_link(catalog, REG_DP_MAINLINK_CTRL, val);
+}
+
 void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
bool enable)
 {
@@ -610,6 +636,47 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog 
*dp_catalog)
dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN);
 }
 
+static void dp_catalog_enable_sdp(struct dp_catalog_private *catalog)
+{
+   /* trigger sdp */
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, UPDATE_SDP);
+   dp_write_link(catalog, MMSS_DP_SDP_CFG3, !UPDATE_SDP);
+}
+
+void dp_catalog_ctrl_config_psr(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 config;
+
+   /* enable PSR1 function */
+   config = dp_read_link(catalog, REG_PSR_CONFIG);
+   config |= PSR1_SUPPORTED;
+   dp_write_link(catalog, REG_PSR_CONFIG, config);
+
+   dp_write_ahb(catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
+   dp_catalog_enable_sdp(catalog);
+}
+
+void dp_catalog_ctrl_set_psr(struct dp_catalog *dp_catalog, bool enter)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 cmd;
+
+   cmd = dp_read_link(catalog, REG_PSR_CMD);
+
+   cmd &= ~(PSR_ENTER | PSR_EXIT);
+
+   if (enter)
+   cmd |= PSR_ENTER;
+   else
+   cmd |= PSR_EXIT;
+
+   dp_catalog_enable_sdp(catalog);
+   dp_write_link(catalog, REG_PSR_CMD, cmd);
+}
+
 u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
 {
struct dp_catalog_private *catalog = container_of(dp_catalog,
@@ -645,6 +712,20 @@ u32 dp_catalog_hpd_get_intr_status(struct dp_catalog 
*dp_catalog)
return isr & (mask | ~DP_DP_HPD_INT_MASK);
 }
 
+int dp_catalog_ctrl_read_psr_interrupt_status(struct dp_catalog *dp_catalog)
+{
+   struct dp_catalog_private *catalog = container_of(dp_catalog,
+   struct dp_catalog_private, dp_catalog);
+   u32 intr, intr_ack;
+
+   intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS4);
+   intr_ack = (intr & DP_INTERRUPT_STATUS4)
+   << DP_INTERRUPT_STATUS_ACK_SHIFT;
+   dp_write_ahb(catalog, REG_DP_INTR_STATUS4, intr_ack);
+
+   return intr;
+}
+
 int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog)
 {
struct dp_catalog_private *catalog = container_of(dp_catalog,
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 1f717f4..6454845 100644
---