On Thu, Jan 30, 2025 at 11:45:17AM -0500, Detlev Casanova wrote: > From: Sugar Zhang <sugar.zhang@xxxxxxxxxxxxxx> > > Register the dw-hdmi-qp bridge driver as an HDMI audio codec. > > The register values computation functions (for n) are based on the > downstream driver, as well as the register writing functions. > > The driver uses the generic HDMI Codec framework in order to implement > the HDMI audio support. > > Signed-off-by: Sugar Zhang <sugar.zhang@xxxxxxxxxxxxxx> > Signed-off-by: Detlev Casanova <detlev.casanova@xxxxxxxxxxxxx> > --- > drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 497 +++++++++++++++++++ > 1 file changed, 497 insertions(+) > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c > index b281cabfe992e..7937504c2dcef 100644 > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c > @@ -36,6 +36,88 @@ > > #define SCRAMB_POLL_DELAY_MS 3000 > > +/* > + * Unless otherwise noted, entries in this table are 100% optimization. > + * Values can be obtained from hdmi_compute_n() but that function is > + * slow so we pre-compute values we expect to see. > + * > + * The values for TMDS 25175, 25200, 27000, 54000, 74250 and 148500 kHz are > + * the recommended N values specified in the Audio chapter of the HDMI > + * specification. > + */ > +static const struct dw_hdmi_audio_tmds_n { > + unsigned long tmds; > + unsigned int n_32k; > + unsigned int n_44k1; > + unsigned int n_48k; > +} common_tmds_n_table[] = { > + { .tmds = 25175000, .n_32k = 4576, .n_44k1 = 7007, .n_48k = 6864, }, > + { .tmds = 25200000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, > + { .tmds = 27000000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, > + { .tmds = 28320000, .n_32k = 4096, .n_44k1 = 5586, .n_48k = 6144, }, > + { .tmds = 30240000, .n_32k = 4096, .n_44k1 = 5642, .n_48k = 6144, }, > + { .tmds = 31500000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, }, > + { .tmds = 32000000, .n_32k = 4096, .n_44k1 = 5733, .n_48k = 6144, }, > + { .tmds = 33750000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, > + { .tmds = 36000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, }, > + { .tmds = 40000000, .n_32k = 4096, .n_44k1 = 5733, .n_48k = 6144, }, > + { .tmds = 49500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, > + { .tmds = 50000000, .n_32k = 4096, .n_44k1 = 5292, .n_48k = 6144, }, > + { .tmds = 54000000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, > + { .tmds = 65000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, > + { .tmds = 68250000, .n_32k = 4096, .n_44k1 = 5376, .n_48k = 6144, }, > + { .tmds = 71000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, > + { .tmds = 72000000, .n_32k = 4096, .n_44k1 = 5635, .n_48k = 6144, }, > + { .tmds = 73250000, .n_32k = 11648, .n_44k1 = 14112, .n_48k = 6144, }, > + { .tmds = 74250000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, > + { .tmds = 75000000, .n_32k = 4096, .n_44k1 = 5880, .n_48k = 6144, }, > + { .tmds = 78750000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, }, > + { .tmds = 78800000, .n_32k = 4096, .n_44k1 = 5292, .n_48k = 6144, }, > + { .tmds = 79500000, .n_32k = 4096, .n_44k1 = 4704, .n_48k = 6144, }, > + { .tmds = 83500000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, > + { .tmds = 85500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, > + { .tmds = 88750000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, }, > + { .tmds = 97750000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, }, > + { .tmds = 101000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, > + { .tmds = 106500000, .n_32k = 4096, .n_44k1 = 4704, .n_48k = 6144, }, > + { .tmds = 108000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, }, > + { .tmds = 115500000, .n_32k = 4096, .n_44k1 = 5712, .n_48k = 6144, }, > + { .tmds = 119000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, }, > + { .tmds = 135000000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, > + { .tmds = 146250000, .n_32k = 11648, .n_44k1 = 6272, .n_48k = 6144, }, > + { .tmds = 148500000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, > + { .tmds = 154000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, }, > + { .tmds = 162000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, }, > + > + /* For 297 MHz+ HDMI spec have some other rule for setting N */ > + { .tmds = 297000000, .n_32k = 3073, .n_44k1 = 4704, .n_48k = 5120, }, > + { .tmds = 594000000, .n_32k = 3073, .n_44k1 = 9408, .n_48k = 10240,}, > + > + /* End of table */ > + { .tmds = 0, .n_32k = 0, .n_44k1 = 0, .n_48k = 0, }, > +}; > + > +/* > + * These are the CTS values as recommended in the Audio chapter of the HDMI > + * specification. > + */ > +static const struct dw_hdmi_audio_tmds_cts { > + unsigned long tmds; > + unsigned int cts_32k; > + unsigned int cts_44k1; > + unsigned int cts_48k; > +} common_tmds_cts_table[] = { > + { .tmds = 25175000, .cts_32k = 28125, .cts_44k1 = 31250, .cts_48k = 28125, }, > + { .tmds = 25200000, .cts_32k = 25200, .cts_44k1 = 28000, .cts_48k = 25200, }, > + { .tmds = 27000000, .cts_32k = 27000, .cts_44k1 = 30000, .cts_48k = 27000, }, > + { .tmds = 54000000, .cts_32k = 54000, .cts_44k1 = 60000, .cts_48k = 54000, }, > + { .tmds = 74250000, .cts_32k = 74250, .cts_44k1 = 82500, .cts_48k = 74250, }, > + { .tmds = 148500000, .cts_32k = 148500, .cts_44k1 = 165000, .cts_48k = 148500, }, > + > + /* End of table */ > + { .tmds = 0, .cts_32k = 0, .cts_44k1 = 0, .cts_48k = 0, }, > +}; > + > struct dw_hdmi_qp_i2c { > struct i2c_adapter adap; > > @@ -60,6 +142,8 @@ struct dw_hdmi_qp { > } phy; > > struct regmap *regm; > + > + unsigned long tmds_char_rate; > }; > > static void dw_hdmi_qp_write(struct dw_hdmi_qp *hdmi, unsigned int val, > @@ -83,6 +167,354 @@ static void dw_hdmi_qp_mod(struct dw_hdmi_qp *hdmi, unsigned int data, > regmap_update_bits(hdmi->regm, reg, mask, data); > } > > +static struct dw_hdmi_qp *dw_hdmi_qp_from_bridge(struct drm_bridge *bridge) > +{ > + return container_of(bridge, struct dw_hdmi_qp, bridge); > +} > + > +static void hdmi_set_cts_n(struct dw_hdmi_qp *hdmi, unsigned int cts, > + unsigned int n) I'm sorry, I should have pointed out in the previous review cycle. Could you please rename those functions so that their name start with dw_hdmi_qp_*. Other than that: Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> > +{ > + /* Set N */ > + dw_hdmi_qp_mod(hdmi, n, AUDPKT_ACR_N_VALUE, AUDPKT_ACR_CONTROL0); > + > + /* Set CTS */ > + if (cts) > + dw_hdmi_qp_mod(hdmi, AUDPKT_ACR_CTS_OVR_EN, AUDPKT_ACR_CTS_OVR_EN_MSK, > + AUDPKT_ACR_CONTROL1); > + else > + dw_hdmi_qp_mod(hdmi, 0, AUDPKT_ACR_CTS_OVR_EN_MSK, > + AUDPKT_ACR_CONTROL1); > + > + dw_hdmi_qp_mod(hdmi, AUDPKT_ACR_CTS_OVR_VAL(cts), AUDPKT_ACR_CTS_OVR_VAL_MSK, > + AUDPKT_ACR_CONTROL1); > +} > + -- With best wishes Dmitry