Re: [PATCH v3 3/3] drm/bridge: parade-ps8640: Add support for AUX channel

From: Doug Anderson
Date: Thu Sep 16 2021 - 16:31:18 EST


Hi,

On Thu, Sep 16, 2021 at 1:15 PM Stephen Boyd <swboyd@xxxxxxxxxxxx> wrote:
>
> > > > + return ret;
> > > > + }
> > > > +
> > > > + /* Assume it's good */
> > > > + msg->reply = 0;
> > > > +
> > > > + addr_len[0] = msg->address & 0xff;
> > > > + addr_len[1] = (msg->address >> 8) & 0xff;
> > > > + addr_len[2] = ((msg->request << 4) & SWAUX_CMD_MASK) |
> > > > + ((msg->address >> 16) & SWAUX_ADDR_19_16_MASK);
> > >
> > > It really feels like this out to be possible with some sort of
> > > cpu_to_le32() API. We're shoving msg->address into 3 bytes and then
> > > adding in the request and some length. So we could do something like:
> > >
> > > u32 addr_len;
> > >
> > > addr_len = FIELD_PREP(SWAUX_ADDR_MASK, msg->address);
> > > addr_len |= FIELD_PREP(SWAUX_CMD_MASK, msg->request);
> > > if (len)
> > > addr_len |= FIELD_PREP(LEN_MASK, len - 1);
> > > else
> > > addr_len |= FIELD_PREP(LEN_MASK, SWAUX_NO_PAYLOAD );
> > >
> > > cpu_to_le32s(&addr_len);
> > >
> > > regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, &addr_len, sizeof(addr_len));
> >
> > You're arguing that your version of the code is more efficient? Easier
> > to understand? Something else? To me, Philip's initial version is
> > crystal clear and easy to map to the bridge datasheet but I need to
> > think more to confirm that your version is right. Thinking is hard and
> > I like to avoid it when possible.
> >
> > In any case, it's definitely bikeshedding and I'll yield if everyone
> > likes the other version better. ;-)
>
> Yeah it's bikeshedding. I don't really care about this either but I find
> it easier to read when the assignment isn't wrapped across multiple
> lines. If the buffer approach is preferable then maybe use the address
> macros to clarify which register is being set?
>
> unsigned int base = PAGE0_SWAUX_ADDR_7_0;
>
> addr_len[PAGE0_SWAUX_ADDR_7_0 - base] = msg->address;
> addr_len[PAGE0_SWAUX_ADDR_15_8 - base] = msg->address >> 8;
> addr_len[PAGE0_SWAUX_ADDR_23_16 - base] = msg->address >> 16;
> addr_len[PAGE0_SWAUX_ADDR_23_16 - base] |= msg->request << 4;

Sure, this looks nice to me. :-)


> > > > + return ret;
> > > > + }
> > > > +
> > > > + switch (data & SWAUX_STATUS_MASK) {
> > > > + /* Ignore the DEFER cases as they are already handled in hardware */
> > > > + case SWAUX_STATUS_NACK:
> > > > + case SWAUX_STATUS_I2C_NACK:
> > > > + /*
> > > > + * The programming guide is not clear about whether a I2C NACK
> > > > + * would trigger SWAUX_STATUS_NACK or SWAUX_STATUS_I2C_NACK. So
> > > > + * we handle both cases together.
> > > > + */
> > > > + if (is_native_aux)
> > > > + msg->reply |= DP_AUX_NATIVE_REPLY_NACK;
> > > > + else
> > > > + msg->reply |= DP_AUX_I2C_REPLY_NACK;
> > > > +
> > > > + len = data & SWAUX_M_MASK;
> > > > + return len;
> > >
> > > Why no 'return data & SWAUX_M_MASK;' and skip the assignment?
> >
> > Actually, I think it's the "return" that's a bug, isn't it? If we're
> > doing a "read" and we're returning a positive number of bytes then we
> > need to actually _read_ them. Reading happens below, doesn't it?
> >
>
> Oh I missed that. We're still supposed to return data to upper
> layers on a NACKed read?

It seems highly likely not to matter in practice, but:

* The docs from parade clearly state that when a NAK is returned that
the number of bytes transferred before the NAK will be provided to us.

* The i2c interface specifies NAK not as a return code but as a bit in
the "reply". That presumably is to let us return the number of bytes
transferred before the NAK to the next level up.

* If we're returning the number of bytes and it's a read then we'd
better return the data too!

It looks like we handled this OK in the TI bridge driver. From reading
the TI docs we'll get both AUX_IRQ_STATUS_AUX_SHORT and
AUX_IRQ_STATUS_NAT_I2C_FAIL in the case of a partial transfer and so
we'll do the right thing.

-Doug