TAS2110 Linux driver interrupt handler after amplifier clipping

Continuing the discussion from [TAS2557 / TAS2563] Implement driver from kernel source:

Hello,
I would like to return to this topic.
I prepared a driver which initializes TAS2110 with default settings. Now I try adding interrupt managing. One thing is crucial for me - when I set source over volume then TAS2110 is clipping and stops working - reports interrupt (need new initialization - reset and sent via I2C power on). The problem is that when TAS2110 reports an interrupt state, the kernel doesn’t know that TAS2110 needs to reinitialize (TAS2110 isn’t initialized during start play every sound). I would like to know how to reset the flag, which tells the kernel that TAS2110 was initialized. When I will know it, I will reset this flag in interrupt then during play the next sound TAS2110 will initialize again.
I hope that you understand my problem. If not I need a proposition on how to manage to interrupt after setting source over volume - TAS2110 reports interrupt.
My current driver:
tas2110.c (14.3 KB)
tas2110.h (3.3 KB)

device tree:

i2c@7000c500 { /* i2c3 */
		status = "okay";
		tas2110_codec: tas2110@4c {
	        #address-cells = <1>;
	        #size-cells = <0>;
	        compatible = "ti,tas2110";
	        reg = <0x4c>;
		 		 
			interrupt-parent = <&gpio>;
			interrupts = <20 IRQ_TYPE_EDGE_FALLING>;
			ti,gpio-irq = <&gpio 20 GPIO_ACTIVE_HIGH>;
			ti,gpio-sdz = <&gpio 200 GPIO_ACTIVE_HIGH>;

		};
	};

Hi Mateusz,
If I understand your problem correctly, you like to avoid interrupt_flag set/reset in interrupt context which will avoid re-initialization of codec for every playback.

One clarification, What do you mean by “when I set source over volume then TAS2110 is clipping and stops working” Can you elaborate abit on this steps.

The piece of code with “if(interrupt_flag){ …}” shouldn’t be there in tas2110_set_bias_level function . I see you are already doing codec reset in probe call. So this is enough if power is supply is not distrubed. We might need to understand why the re-initialization required.

Can you dump all the interrupt related register during the error case in interrupt handler. This might give some clue on why there is a hardware reset happened which required re-initialization.

When I set the high volume on the source in Linux the amplifier return interrupts (Over Current Error and TDM Clock Error). I want to return this info to dmesg (it works now) and manage this interrupt. If there is an interrupt, the amplifier will not work when the next sound is played.
(need reinitializing). I don’t know where I can add this reinitialized. I do not want to add interrupt manage in the interrupt handler, because I must HW reset TAS2110 and send one I2C command.

I know it that it doesn’t the best solution but I checked that this function is called most often. If, you have any idea where I can put this interrupt managing (interrupt handler is in driver now) please tell me.

As I wrote above, TAS2110 returns that problems are in Over Current Error and TDM Clock Error. The reason for these interrupt flags is not the best layout of the PCB (it is prototype now) and I want to manage these errors when occur.

Thanks got it.

May be you need to create worker thread and queue up the worker thread in interrupt handler when you detect error and it need hw reset. This would be best way to avoid handling reset in interrupt handler and also you can remove the reset code from bias call.

Can you explain more about how this should be done?

Reference: rt711.c - sound/soc/codecs/rt711.c - Linux source code (v5.19.9) - Bootlin in upstream driver for a codec.

The Worker thread can help to run a piece of code or function independent to current code flow. As we need to avoid interrupt context this will help to schedule the thread to call the worker callback function. If we need some delay after interrupt handler call you can use INIT_DELAYED_WOR or INIT_WORK

So whenever there is an interrupt handler call and detected error, we can schedule the worker to do the reset, re-initialize codec.

Hello,

I added interrupt handlers and scheduled thread. It works fine. But I have a problem with the correct detect interrupt. I set that interrupt is detected when the IRQ pin is in a low state, but the interrupt is detected when the IRQ pin has fallen to 1.46V. I tested two types of detect interrupts: edge falling and low state. Both interrupts are detected the same. It’s sum up, I want to detect interrupt in the low state because I have some unstable high state on the IRQ pin (pull up resistor 1k). Can you check my interrupt settings?

		tas2xxx_codec: tas2xxx@4c {
	        #address-cells = <1>;
	        #size-cells = <0>;
	        compatible = "ti,tas2xxx";
	        reg = <0x4c>;
			
			interrupt-parent = <&gpio>;
			interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
			ti,gpio-irq = <&gpio 20 GPIO_ACTIVE_HIGH>;
			ti,gpio-sdz = <&gpio 200 GPIO_ACTIVE_HIGH>;
		};

tas2xxx.c (13.7 KB)
tas2xxx.h (3.4 KB)

Hi Mateusz,
Though I don’t see any issue with your DT node and driver which uses interrupt detect in low state.

Also check MISC_CFG1 (page=0x00 address=0x04) [reset=C6h] register for pull up config IRQZ_PU(3rd) bitfield which is disabled by default, May be can try enabling it.

But I recommend to contact Codec vendor(TI) on this query, as this is related to codec specific.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.