[PATCH 1/4] drm/rockchip: add transfer function for cdn-dp
hl
hl at rock-chips.com
Tue May 8 19:59:32 PDT 2018
Hi Enric,
On Monday, May 07, 2018 07:27 PM, Enric Balletbo Serra wrote:
> Hi Lin,
>
> I am interested in these patches, could you cc me on newer versions? Thanks.
>
> Some comments below.
Sure, will cc to you next version.
>
> 2018-05-04 10:08 GMT+02:00 Lin Huang <hl at rock-chips.com>:
>> From: Chris Zhong <zyw at rock-chips.com>
>>
>> We may support training outside firmware, so we need support
>> dpcd read/write to get the message or do some setting with
>> display.
>>
>> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
>> Signed-off-by: Lin Huang <hl at rock-chips.com>
>> ---
>> drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 ++++++++++++++++++++++++----
>> drivers/gpu/drm/rockchip/cdn-dp-core.h | 1 +
>> drivers/gpu/drm/rockchip/cdn-dp-reg.c | 66 +++++++++++++++++++++++++++++-----
>> drivers/gpu/drm/rockchip/cdn-dp-reg.h | 14 ++++++--
>> 4 files changed, 119 insertions(+), 17 deletions(-)
>>
> In general, for this patch and all the other patches in the series I
> saw that checkpatch spits out some warnings, could you fix these and
> ideally run checkpatch with the --strict --subjective option?
Okay.
>
>> diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
>> index c6fbdcd..268c190 100644
>> --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
>> +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
>> @@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, u8 *sink_count)
>> u8 value;
>>
>> *sink_count = 0;
>> - ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, &value, 1);
>> - if (ret)
>> + ret = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, &value, 1);
>> + if (ret < 0)
>> return ret;
>>
>> *sink_count = DP_GET_SINK_COUNT(value);
>> @@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp)
>> if (!cdn_dp_check_sink_connection(dp))
>> return -ENODEV;
>>
>> - ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
>> - DP_RECEIVER_CAP_SIZE);
>> - if (ret) {
>> + ret = drm_dp_dpcd_read(&dp->aux, DP_DPCD_REV, dp->dpcd,
>> + sizeof(dp->dpcd));
>> + if (ret < 0) {
>> DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
>> return ret;
>> }
>> @@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device *dp)
>> if (!port || !dp->link.rate || !dp->link.num_lanes)
>> return false;
>>
>> - if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
>> - DP_LINK_STATUS_SIZE)) {
>> + if (drm_dp_dpcd_read_link_status(&dp->aux, link_status) !=
>> + DP_LINK_STATUS_SIZE) {
>> DRM_ERROR("Failed to get link status\n");
>> return false;
>> }
>> @@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
>> return NOTIFY_DONE;
>> }
>>
>> +static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
>> + struct drm_dp_aux_msg *msg)
>> +{
>> + struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
>> + int ret;
>> + u8 status;
>> +
>> + switch (msg->request & ~DP_AUX_I2C_MOT) {
>> + case DP_AUX_NATIVE_WRITE:
>> + case DP_AUX_I2C_WRITE:
>> + case DP_AUX_I2C_WRITE_STATUS_UPDATE:
>> + ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
>> + msg->size);
>> + break;
>> + case DP_AUX_NATIVE_READ:
>> + case DP_AUX_I2C_READ:
>> + ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
>> + msg->size);
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + status = cdn_dp_get_aux_status(dp);
>> + if (status == AUX_STAUS_ACK)
>> + msg->reply = DP_AUX_NATIVE_REPLY_ACK;
>> + else if (status == AUX_STAUS_NACK)
>> + msg->reply = DP_AUX_NATIVE_REPLY_NACK;
>> + else if (status == AUX_STAUS_DEFER)
>> + msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
>> +
> I think that you would mean STATUS instead of STAUS on these defines.
>
> What happens if the status is AUX_STATUS_SINK_ERROR or AUX_STATUS_BUS_ERROR?
drm_dp_i2c_do_msg() will mark it as invalid i2c relay and return error.
>
>> + return ret;
>> +}
>> +
>> static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
>> {
>> struct cdn_dp_device *dp = dev_get_drvdata(dev);
>> @@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
>> dp->active = false;
>> dp->active_port = -1;
>> dp->fw_loaded = false;
>> + dp->aux.name = "DP-AUX";
>> + dp->aux.transfer = cdn_dp_aux_transfer;
>> + dp->aux.dev = dev;
>> +
>> + ret = drm_dp_aux_register(&dp->aux);
>> + if (ret)
>> + return ret;
>>
>> INIT_WORK(&dp->event_work, cdn_dp_pd_event_work);
>>
>> diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
>> index f57e296..46159b2 100644
>> --- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
>> +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
>> @@ -78,6 +78,7 @@ struct cdn_dp_device {
>> struct platform_device *audio_pdev;
>> struct work_struct event_work;
>> struct edid *edid;
>> + struct drm_dp_aux aux;
>>
>> struct mutex lock;
>> bool connected;
>> diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
>> index eb3042c..b2f532a 100644
>> --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
>> +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
>> @@ -221,7 +221,11 @@ static int cdn_dp_reg_write_bit(struct cdn_dp_device *dp, u16 addr,
>> sizeof(field), field);
>> }
>>
>> -int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
>> +/*
>> + * Returns the number of bytes transferred on success, or a negative error
>> + * code on failure. -ETIMEDOUT is returned if mailbox message not send success;
>> + */
> Returns the number of bytes or -ETIMEDOUT, no other negative errors
> can be returned, right?
>
> I am not English native but the last phrase sounds incorrect to me,
> I'd rephrase it: (open to suggestions)
>
> -ETIMEDOUT if fails to receive the mailbox message.
>
>> +ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
>> {
>> u8 msg[5], reg[5];
>> int ret;
>> @@ -247,24 +251,40 @@ int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
>> goto err_dpcd_read;
>>
>> ret = cdn_dp_mailbox_read_receive(dp, data, len);
>> + if (!ret)
>> + return len;
>>
>> err_dpcd_read:
>> + DRM_DEV_ERROR(dp->dev, "dpcd read failed: %d\n", ret);
>> return ret;
>> }
>>
>> -int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
>> +#define CDN_AUX_HEADER_SIZE 5
>> +#define CDN_AUX_MSG_SIZE 20
>> +/*
>> + * Returns the number of bytes transferred on success, or a negative error
>> + * code on failure. -ETIMEDOUT is returned if mailbox message not send success;
> Same as above. Sounds incorrect to me.
>
>> + * -EINVAL is return if get the wrong data size after message send.
> Same here.
>
>> + */
>> +ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
>> {
>> - u8 msg[6], reg[5];
>> + u8 msg[CDN_AUX_MSG_SIZE + CDN_AUX_HEADER_SIZE];
>> + u8 reg[CDN_AUX_HEADER_SIZE];
>> int ret;
>>
>> - msg[0] = 0;
>> - msg[1] = 1;
>> + if (WARN_ON(len > CDN_AUX_MSG_SIZE) || WARN_ON(len <= 0))
>> + return -EINVAL;
>> +
>> + msg[0] = (len >> 8) & 0xff;
>> + msg[1] = len & 0xff;
>> msg[2] = (addr >> 16) & 0xff;
>> msg[3] = (addr >> 8) & 0xff;
>> msg[4] = addr & 0xff;
>> - msg[5] = value;
>> +
>> + memcpy(msg + CDN_AUX_HEADER_SIZE, data, len);
>> +
>> ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_DPCD,
>> - sizeof(msg), msg);
>> + CDN_AUX_HEADER_SIZE + len, msg);
>> if (ret)
>> goto err_dpcd_write;
>>
>> @@ -277,8 +297,12 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
>> if (ret)
>> goto err_dpcd_write;
>>
>> - if (addr != (reg[2] << 16 | reg[3] << 8 | reg[4]))
>> + if ((len != (reg[0] << 8 | reg[1])) ||
>> + (addr != (reg[2] << 16 | reg[3] << 8 | reg[4]))) {
>> ret = -EINVAL;
>> + } else {
>> + return len;
>> + }
>>
>> err_dpcd_write:
>> if (ret)
>> @@ -286,6 +310,32 @@ int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
>> return ret;
>> }
>>
>> +int cdn_dp_get_aux_status(struct cdn_dp_device *dp)
>> +{
>> + u8 status;
>> + int ret;
>> +
>> + ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_GET_LAST_AUX_STAUS,
>> + 0, NULL);
>> + if (ret)
>> + goto err_get_hpd;
>> +
>> + ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX,
>> + DPTX_GET_LAST_AUX_STAUS, sizeof(status));
>> + if (ret)
>> + goto err_get_hpd;
>> +
>> + ret = cdn_dp_mailbox_read_receive(dp, &status, sizeof(status));
>> + if (ret)
>> + goto err_get_hpd;
>> +
>> + return status;
>> +
>> +err_get_hpd:
>> + DRM_DEV_ERROR(dp->dev, "get aux status failed: %d\n", ret);
>> + return ret;
>> +}
>> +
>> int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
>> u32 i_size, const u32 *d_mem, u32 d_size)
>> {
>> diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
>> index c4bbb4a83..aedf2dc 100644
>> --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h
>> +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
>> @@ -328,6 +328,13 @@
>> #define GENERAL_BUS_SETTINGS 0x03
>> #define GENERAL_TEST_ACCESS 0x04
>>
>> +/* AUX status*/
>> +#define AUX_STAUS_ACK 0
>> +#define AUX_STAUS_NACK 1
>> +#define AUX_STAUS_DEFER 2
>> +#define AUX_STAUS_SINK_ERROR 3
>> +#define AUX_STAUS_BUS_ERROR 4
>> +
> For the five defines, s/STAUS/STATUS/
will fix it.
>
>> #define DPTX_SET_POWER_MNG 0x00
>> #define DPTX_SET_HOST_CAPABILITIES 0x01
>> #define DPTX_GET_EDID 0x02
>> @@ -469,8 +476,11 @@ int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip);
>> int cdn_dp_event_config(struct cdn_dp_device *dp);
>> u32 cdn_dp_get_event(struct cdn_dp_device *dp);
>> int cdn_dp_get_hpd_status(struct cdn_dp_device *dp);
>> -int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value);
>> -int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len);
>> +ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr,
>> + u8 *data, u16 len);
>> +ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr,
>> + u8 *data, u16 len);
>> +int cdn_dp_get_aux_status(struct cdn_dp_device *dp);
>> int cdn_dp_get_edid_block(void *dp, u8 *edid,
>> unsigned int block, size_t length);
>> int cdn_dp_train_link(struct cdn_dp_device *dp);
>> --
>> 2.7.4
>>
>>
>> _______________________________________________
>> Linux-rockchip mailing list
>> Linux-rockchip at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-rockchip
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>
>
>
More information about the Linux-rockchip
mailing list