[PATCH v4 02/13] ASoC: Intel: catpt: Define DSP operations
Cezary Rojewski
cezary.rojewski at intel.com
Mon Aug 17 13:12:01 CEST 2020
On 2020-08-13 8:51 PM, Andy Shevchenko wrote:
> On Wed, Aug 12, 2020 at 10:57:42PM +0200, Cezary Rojewski wrote:
>> Implement dsp lifecycle functions such as core RESET and STALL,
>> SRAM power control and LP clock selection. This also adds functions for
>> handling transport over DW DMA controller.
Thanks for your input Andy!
>> +static void catpt_dma_transfer_complete(void *arg)
>> +{
>> + struct catpt_dev *cdev = arg;
>> +
>
>> + dev_dbg(cdev->dev, "%s\n", __func__);
>
> Noise. Somebody should provide either trace events, of get used to function tracer / perf.
>
Agree. Don't have much expertise with DMA-engine and some stuff is based
on existing stuff:
/sound/soc/intel/common/sst-firmware.c ::sst_dma_transfer_complete()
That's not somebody - that's CI. I don't mind ftracer, but our's CI
logging is currently dmesg/ event traces -based.
Anyway, with log removed, catpt_dma_transfer_complete() ceases to exist too.
>
>> +static bool catpt_dma_filter(struct dma_chan *chan, void *param)
>> +{
>
>> + return chan->device->dev == (struct device *)param;
>
> Redundant casting, and please, consider to swap left and right side (in this
> case easily to find these and perhaps provide a generic helper function).
>
Good point. Yeah, I've tried to find generic-helper before even adding
this, but with no result.
>
>> +#define CATPT_DMA_DEVID 1 /* dma engine used */
>
> Not sure I understand what exactly this means.
>
Well, you may choose either engine 0 or 1 for loading images. Reference
solution which I'm basing catpt on - Windows driver equivalent - makes
use of engine 1. Goal of this implementation is to align closely to
stable Windows solution wherever possible to reduce maintainance cost.
>
>> +#define CATPT_DMA_MAXBURST 0x3
>
> We have DMA engine definitions for that, please avoid magic numbers.
>
As with most of the dma stuff, based on existing:
/sound/soc/intel/common/sst-firmware.c SST_DSP_DMA_MAX_BURST
Ack.
>> +#define CATPT_DMA_DSP_ADDR_MASK 0xFFF00000
>
> GENMASK()
>
Ditto as above. Ack.
>> + dma_cap_set(DMA_SLAVE, mask);
>
> How this helps with mem2mem channel?
>
> ...
>
>> + chan = dma_request_channel(mask, catpt_dma_filter, cdev->dev);
>> + if (!chan) {
>> + dev_err(cdev->dev, "request channel failed\n");
>
>> + dump_stack();
>
> Huh?!
>
I'm as surpriced as you : )
Remnant of pm_runtime + single platform_device (for adsp and dw both)
debug. Removed in v5.
>> + return ERR_PTR(-EPROBE_DEFER);
>> + }
>
> ...
>
>> + status = dma_wait_for_async_tx(desc);
>
>> + catpt_updatel_shim(cdev, HMDC,
>> + CATPT_HMDC_HDDA(CATPT_DMA_DEVID, chan->chan_id), 0);
>
> Update even in erroneous case?
>
Yes. This is based on stable Windows solution equivalent and get's
updated even in failure case to disable access to HOST memory in demand
more.
>> + return (status == DMA_COMPLETE) ? 0 : -EPROTO;
>
> ...
>
>> +static void catpt_dsp_set_srampge(struct catpt_dev *cdev, struct resource *sram,
>> + unsigned long mask, unsigned long new)
>> +{
>> + unsigned long old;
>> + u32 off = sram->start;
>> + u32 b = __ffs(mask);
>> +
>> + old = catpt_readl_pci(cdev, VDRTCTL0) & mask;
>
>> + dev_dbg(cdev->dev, "SRAMPGE [0x%08lx] 0x%08lx -> 0x%08lx",
>> + mask, old, new);
>
> trace event / point?
>
Well, I've just replaced these with dev_dbg (from trace events). Not
many usages and caused all reg-related prints to be available in dmesg.
>> + if (old == new)
>> + return;
>> +
>> + catpt_updatel_pci(cdev, VDRTCTL0, mask, new);
>
>> + udelay(60);
>
> Delays should be commented.
>
Similarly to previous review (comment regarding hw support), I'm afraid
I don't have good comments for most occurences available.
I'll try to add something meaningful for at least some of these.
>> +
>> + /*
>> + * dummy read as the very first access after block enable
>> + * to prevent byte loss in future operations
>> + */
>> + for_each_clear_bit_from(b, &new, fls(mask)) {
>
> fls_long()
>
Ack.
>> + u8 buf[4];
>> +
>> + /* newly enabled: new bit=0 while old bit=1 */
>> + if (test_bit(b, &old)) {
>> + dev_dbg(cdev->dev, "sanitize block %ld: off 0x%08x\n",
>
>> + (b - __ffs(mask)), off);
>
> Unneeded parentheses.
>
Ack.
>> + memcpy_fromio(buf, cdev->lpe_ba + off, sizeof(buf));
>> + }
>> + off += CATPT_MEMBLOCK_SIZE;
>> + }
>> +}
>
> ...
>
>> + /* offset value given mask's start and invert it as ON=b0 */
>
>> + new <<= __ffs(mask);
>> + new = ~(new) & mask;
>
> Unneeded parentheses.
> And perhaps in one line it will be better to understand:
>
> new = ~(new << __ffs(mask)) & mask;
>
Was called out in the past not to combine everything in one-line like if
I'm to hide something from reviewer.
No problem with combining these together in v5.
>> + if (waiti) {
>> + /* wait for DSP to signal WAIT state */
>> + ret = catpt_readl_poll_shim(cdev, ISD,
>> + reg, (reg & CATPT_ISD_DCPWM),
>> + 500, 10000);
>> + if (ret < 0) {
>
>> + dev_warn(cdev->dev, "await WAITI timeout\n");
>
> Shouldn't be an error level?
>
As this causes early return, I agree.
>> + mutex_unlock(&cdev->clk_mutex);
>> + return ret;
>> + }
>> + }
>
> ...
>
>> +int catpt_dsp_update_lpclock(struct catpt_dev *cdev)
>> +{
>> + struct catpt_stream_runtime *stream;
>
>> + bool lp;
>> +
>> + if (list_empty(&cdev->stream_list))
>> + return catpt_dsp_select_lpclock(cdev, true, true);
>> +
>> + lp = true;
>> + list_for_each_entry(stream, &cdev->stream_list, node) {
>> + if (stream->prepared) {
>> + lp = false;
>> + break;
>> + }
>> + }
>> +
>> + return catpt_dsp_select_lpclock(cdev, lp, true);
>
> Seems too much duplication.
>
> struct catpt_stream_runtime *stream;
>
> list_for_each_entry(stream, &cdev->stream_list, node) {
> if (stream->prepared)
> return catpt_dsp_select_lpclock(cdev, false, true);
> }
>
> return catpt_dsp_select_lpclock(cdev, true, true);
>
>
> Better?
>
list_first_entry (part of list_for_each_entry) expects list to be
non-empty. ->streal_list may be empty when invoking
catpt_dsp_update_lpclock().
>> + /* set D3 */
>> + catpt_updatel_pci(cdev, PMCS, CATPT_PMCS_PS, CATPT_PMCS_PS_D3HOT);
>> + udelay(50);
>
> Don't we have PCI core function for this?
>
> ...
>
>> + /* set D0 */
>> + catpt_updatel_pci(cdev, PMCS, CATPT_PMCS_PS, 0);
>> + udelay(100);
>
> Ditto.
>
> ...
>
>> + /* set D3 */
>> + catpt_updatel_pci(cdev, PMCS, CATPT_PMCS_PS, CATPT_PMCS_PS_D3HOT);
>> + udelay(50);
>
> Ditto.
>
> ...
>
>> + /* set D0 */
>> + catpt_updatel_pci(cdev, PMCS, CATPT_PMCS_PS, 0);
>
> Ditto.
>
Thanks to you now I know the correct answer: yes.
Ack for all of these. Good advice Andy, again!
More information about the Alsa-devel
mailing list