hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/gpu/drm/rockchip/cdn-dp-reg.c
....@@ -181,7 +181,7 @@
181181 return 0;
182182 }
183183
184
-static int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val)
184
+int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val)
185185 {
186186 u8 msg[6];
187187
....@@ -213,7 +213,12 @@
213213 sizeof(field), field);
214214 }
215215
216
-int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
216
+/*
217
+ * Returns the number of bytes transferred on success, or a negative
218
+ * error code on failure. -ETIMEDOUT is returned if mailbox message was
219
+ * not send successfully;
220
+ */
221
+ssize_t cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
217222 {
218223 u8 msg[5], reg[5];
219224 int ret;
....@@ -239,24 +244,41 @@
239244 goto err_dpcd_read;
240245
241246 ret = cdn_dp_mailbox_read_receive(dp, data, len);
247
+ if (!ret)
248
+ return len;
242249
243250 err_dpcd_read:
251
+ DRM_DEV_ERROR(dp->dev, "dpcd read failed: %d\n", ret);
244252 return ret;
245253 }
246254
247
-int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
255
+#define CDN_AUX_HEADER_SIZE 5
256
+#define CDN_AUX_MSG_SIZE 20
257
+/*
258
+ * Returns the number of bytes transferred on success, or a negative error
259
+ * code on failure. -ETIMEDOUT is returned if mailbox message was not send
260
+ * success; -EINVAL is returned if get the wrong data size after message
261
+ * is sent
262
+ */
263
+ssize_t cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len)
248264 {
249
- u8 msg[6], reg[5];
265
+ u8 msg[CDN_AUX_MSG_SIZE + CDN_AUX_HEADER_SIZE];
266
+ u8 reg[CDN_AUX_HEADER_SIZE];
250267 int ret;
251268
252
- msg[0] = 0;
253
- msg[1] = 1;
269
+ if (WARN_ON(len > CDN_AUX_MSG_SIZE) || WARN_ON(len <= 0))
270
+ return -EINVAL;
271
+
272
+ msg[0] = (len >> 8) & 0xff;
273
+ msg[1] = len & 0xff;
254274 msg[2] = (addr >> 16) & 0xff;
255275 msg[3] = (addr >> 8) & 0xff;
256276 msg[4] = addr & 0xff;
257
- msg[5] = value;
277
+
278
+ memcpy(msg + CDN_AUX_HEADER_SIZE, data, len);
279
+
258280 ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_DPCD,
259
- sizeof(msg), msg);
281
+ CDN_AUX_HEADER_SIZE + len, msg);
260282 if (ret)
261283 goto err_dpcd_write;
262284
....@@ -269,12 +291,43 @@
269291 if (ret)
270292 goto err_dpcd_write;
271293
272
- if (addr != (reg[2] << 16 | reg[3] << 8 | reg[4]))
294
+ if ((len != (reg[0] << 8 | reg[1])) ||
295
+ (addr != (reg[2] << 16 | reg[3] << 8 | reg[4]))) {
273296 ret = -EINVAL;
297
+ } else {
298
+ return len;
299
+ }
274300
275301 err_dpcd_write:
276302 if (ret)
277303 DRM_DEV_ERROR(dp->dev, "dpcd write failed: %d\n", ret);
304
+ return ret;
305
+}
306
+
307
+int cdn_dp_get_aux_status(struct cdn_dp_device *dp)
308
+{
309
+ u8 status;
310
+ int ret;
311
+
312
+ ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX,
313
+ DPTX_GET_LAST_AUX_STAUS, 0, NULL);
314
+ if (ret)
315
+ goto err_get_hpd;
316
+
317
+ ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX,
318
+ DPTX_GET_LAST_AUX_STAUS,
319
+ sizeof(status));
320
+ if (ret)
321
+ goto err_get_hpd;
322
+
323
+ ret = cdn_dp_mailbox_read_receive(dp, &status, sizeof(status));
324
+ if (ret)
325
+ goto err_get_hpd;
326
+
327
+ return status;
328
+
329
+err_get_hpd:
330
+ DRM_DEV_ERROR(dp->dev, "get aux status failed: %d\n", ret);
278331 return ret;
279332 }
280333
....@@ -535,7 +588,7 @@
535588 if (ret)
536589 goto err_get_training_status;
537590
538
- dp->max_rate = drm_dp_bw_code_to_link_rate(status[0]);
591
+ dp->max_rate = status[0];
539592 dp->max_lanes = status[1];
540593
541594 err_get_training_status:
....@@ -548,6 +601,31 @@
548601 {
549602 int ret;
550603
604
+ /*
605
+ * DP firmware uses fixed phy config values to do training, but some
606
+ * boards need to adjust these values to fit for their unique hardware
607
+ * design. So if the phy is using custom config values, do software
608
+ * link training instead of relying on firmware, if software training
609
+ * fail, keep firmware training as a fallback if sw training fails.
610
+ */
611
+ ret = cdn_dp_software_train_link(dp);
612
+ if (ret) {
613
+ DRM_DEV_ERROR(dp->dev,
614
+ "Failed to do software training %d\n", ret);
615
+ goto do_fw_training;
616
+ }
617
+ ret = cdn_dp_reg_write(dp, SOURCE_HDTX_CAR, 0xf);
618
+ if (ret) {
619
+ DRM_DEV_ERROR(dp->dev,
620
+ "Failed to write SOURCE_HDTX_CAR register %d\n", ret);
621
+ goto do_fw_training;
622
+ }
623
+ dp->use_fw_training = false;
624
+ return 0;
625
+
626
+do_fw_training:
627
+ dp->use_fw_training = true;
628
+ DRM_DEV_DEBUG_KMS(dp->dev, "use fw training\n");
551629 ret = cdn_dp_training_start(dp);
552630 if (ret) {
553631 DRM_DEV_ERROR(dp->dev, "Failed to start training %d\n", ret);
....@@ -639,7 +717,7 @@
639717 bit_per_pix = (video->color_fmt == YCBCR_4_2_2) ?
640718 (video->color_depth * 2) : (video->color_depth * 3);
641719
642
- link_rate = dp->max_rate / 1000;
720
+ link_rate = drm_dp_bw_code_to_link_rate(dp->max_rate) / 1000;
643721
644722 ret = cdn_dp_reg_write(dp, BND_HSYNC2VSYNC, VIF_BYPASS_INTERLACE);
645723 if (ret)