WM8904 interface enable method now returns the previous interrupt state. Correct ordering of some WM8904: Need to provide MCLK before initializing the WM8904, not after

This commit is contained in:
Gregory Nutt
2014-08-04 14:56:20 -06:00
parent eebdae30b2
commit e30d31367a
2 changed files with 104 additions and 66 deletions
+52 -33
View File
@@ -99,7 +99,7 @@ struct sama5d3ek_mwinfo_s
static int wm8904_attach(FAR const struct wm8904_lower_s *lower, static int wm8904_attach(FAR const struct wm8904_lower_s *lower,
wm8904_handler_t isr, FAR void *arg); wm8904_handler_t isr, FAR void *arg);
static void wm8904_enable(FAR const struct wm8904_lower_s *lower, static bool wm8904_enable(FAR const struct wm8904_lower_s *lower,
bool enable); bool enable);
/**************************************************************************** /****************************************************************************
@@ -114,7 +114,7 @@ static void wm8904_enable(FAR const struct wm8904_lower_s *lower,
* by the driver and is presumed to persist while the driver is active. * by the driver and is presumed to persist while the driver is active.
*/ */
static struct sama5d3ek_mwinfo_s g_mxtinfo = static struct sama5d3ek_mwinfo_s g_wm8904info =
{ {
.lower = .lower =
{ {
@@ -158,41 +158,60 @@ static int wm8904_attach(FAR const struct wm8904_lower_s *lower,
*/ */
audvdbg("Attaching %p\n", isr); audvdbg("Attaching %p\n", isr);
g_mxtinfo.handler = isr; g_wm8904info.handler = isr;
g_mxtinfo.arg = arg; g_wm8904info.arg = arg;
} }
else else
{ {
audvdbg("Detaching %p\n", g_mxtinfo.handler); audvdbg("Detaching %p\n", g_wm8904info.handler);
wm8904_enable(lower, false); (void)wm8904_enable(lower, false);
g_mxtinfo.handler = NULL; g_wm8904info.handler = NULL;
g_mxtinfo.arg = NULL; g_wm8904info.arg = NULL;
} }
return OK; return OK;
} }
static void wm8904_enable(FAR const struct wm8904_lower_s *lower, bool enable) static bool wm8904_enable(FAR const struct wm8904_lower_s *lower, bool enable)
{ {
/* Enable or disable interrupts */ static bool enabled;
irqstate_t flags;
bool ret;
if (enable && g_mxtinfo.handler) /* Has the interrupt state changed */
flags = irqsave();
if (enable != enabled)
{ {
sam_pioirqenable(IRQ_INT_WM8904); /* Enable or disable interrupts */
}
else if (enable && g_wm8904info.handler)
{ {
sam_pioirqdisable(IRQ_INT_WM8904); audvdbg("Enabling\n");
sam_pioirqenable(IRQ_INT_WM8904);
enabled = true;
}
else
{
audvdbg("Disabling\n");
sam_pioirqdisable(IRQ_INT_WM8904);
enabled = false;
}
} }
ret = enabled;
irqrestore(flags);
return ret;
} }
static int wm8904_interrupt(int irq, FAR void *context) static int wm8904_interrupt(int irq, FAR void *context)
{ {
/* Just forward the interrupt to the WM8904 driver */ /* Just forward the interrupt to the WM8904 driver */
if (g_mxtinfo.handler) audvdbg("handler %p\n", g_wm8904info.handler);
if (g_wm8904info.handler)
{ {
return g_mxtinfo.handler(&g_mxtinfo.lower, g_mxtinfo.arg); return g_wm8904info.handler(&g_wm8904info.lower, g_wm8904info.arg);
} }
/* We got an interrupt with no handler. This should not /* We got an interrupt with no handler. This should not
@@ -269,18 +288,6 @@ int sam_wm8904_initialize(int minor)
goto errout_with_i2c; goto errout_with_i2c;
} }
/* Now we can use these I2C and I2S interfaces to initialize the
* MW8904 which will return an audio interface.
*/
wm8904 = wm8904_initialize(i2c, i2s, &g_mxtinfo.lower);
if (!wm8904)
{
auddbg("Failed to initialize the WM8904\n");
ret = -ENODEV;
goto errout_with_i2s;
}
/* Configure the DAC master clock. This clock is provided by PCK0 (PD30) /* Configure the DAC master clock. This clock is provided by PCK0 (PD30)
* that is connected to the WM8904 MCLK. * that is connected to the WM8904 MCLK.
*/ */
@@ -307,7 +314,19 @@ int sam_wm8904_initialize(int minor)
if (ret < 0) if (ret < 0)
{ {
auddbg("ERROR: Failed to attach WM8904 interrupt: %d\n", ret); auddbg("ERROR: Failed to attach WM8904 interrupt: %d\n", ret);
goto errout_with_audio; goto errout_with_i2s;
}
/* Now we can use these I2C and I2S interfaces to initialize the
* MW8904 which will return an audio interface.
*/
wm8904 = wm8904_initialize(i2c, i2s, &g_wm8904info.lower);
if (!wm8904)
{
auddbg("Failed to initialize the WM8904\n");
ret = -ENODEV;
goto errout_with_irq;
} }
/* No we can embed the WM8904/I2C/I2S conglomerate into a PCM decoder /* No we can embed the WM8904/I2C/I2S conglomerate into a PCM decoder
@@ -320,7 +339,7 @@ int sam_wm8904_initialize(int minor)
{ {
auddbg("ERROR: Failed create the PCM decoder\n"); auddbg("ERROR: Failed create the PCM decoder\n");
ret = -ENODEV; ret = -ENODEV;
goto errout_with_irq; goto errout_with_wm8904;
} }
/* Create a device name */ /* Create a device name */
@@ -351,9 +370,9 @@ int sam_wm8904_initialize(int minor)
*/ */
errout_with_pcm: errout_with_pcm:
errout_with_wm8904:
errout_with_irq: errout_with_irq:
irq_detach(IRQ_INT_WM8904); irq_detach(IRQ_INT_WM8904);
errout_with_audio:
errout_with_i2s: errout_with_i2s:
errout_with_i2c: errout_with_i2c:
errout: errout:
+52 -33
View File
@@ -99,7 +99,7 @@ struct sama5d4ek_mwinfo_s
static int wm8904_attach(FAR const struct wm8904_lower_s *lower, static int wm8904_attach(FAR const struct wm8904_lower_s *lower,
wm8904_handler_t isr, FAR void *arg); wm8904_handler_t isr, FAR void *arg);
static void wm8904_enable(FAR const struct wm8904_lower_s *lower, static bool wm8904_enable(FAR const struct wm8904_lower_s *lower,
bool enable); bool enable);
/**************************************************************************** /****************************************************************************
@@ -114,7 +114,7 @@ static void wm8904_enable(FAR const struct wm8904_lower_s *lower,
* by the driver and is presumed to persist while the driver is active. * by the driver and is presumed to persist while the driver is active.
*/ */
static struct sama5d4ek_mwinfo_s g_mxtinfo = static struct sama5d4ek_mwinfo_s g_wm8904info =
{ {
.lower = .lower =
{ {
@@ -158,41 +158,60 @@ static int wm8904_attach(FAR const struct wm8904_lower_s *lower,
*/ */
audvdbg("Attaching %p\n", isr); audvdbg("Attaching %p\n", isr);
g_mxtinfo.handler = isr; g_wm8904info.handler = isr;
g_mxtinfo.arg = arg; g_wm8904info.arg = arg;
} }
else else
{ {
audvdbg("Detaching %p\n", g_mxtinfo.handler); audvdbg("Detaching %p\n", g_wm8904info.handler);
wm8904_enable(lower, false); (void)wm8904_enable(lower, false);
g_mxtinfo.handler = NULL; g_wm8904info.handler = NULL;
g_mxtinfo.arg = NULL; g_wm8904info.arg = NULL;
} }
return OK; return OK;
} }
static void wm8904_enable(FAR const struct wm8904_lower_s *lower, bool enable) static bool wm8904_enable(FAR const struct wm8904_lower_s *lower, bool enable)
{ {
/* Enable or disable interrupts */ static bool enabled;
irqstate_t flags;
bool ret;
if (enable && g_mxtinfo.handler) /* Has the interrupt state changed */
flags = irqsave();
if (enable != enabled)
{ {
sam_pioirqenable(IRQ_INT_WM8904); /* Enable or disable interrupts */
}
else if (enable && g_wm8904info.handler)
{ {
sam_pioirqdisable(IRQ_INT_WM8904); audvdbg("Enabling\n");
sam_pioirqenable(IRQ_INT_WM8904);
enabled = true;
}
else
{
audvdbg("Disabling\n");
sam_pioirqdisable(IRQ_INT_WM8904);
enabled = false;
}
} }
ret = enabled;
irqrestore(flags);
return ret;
} }
static int wm8904_interrupt(int irq, FAR void *context) static int wm8904_interrupt(int irq, FAR void *context)
{ {
/* Just forward the interrupt to the WM8904 driver */ /* Just forward the interrupt to the WM8904 driver */
if (g_mxtinfo.handler) audvdbg("handler %p\n", g_wm8904info.handler);
if (g_wm8904info.handler)
{ {
return g_mxtinfo.handler(&g_mxtinfo.lower, g_mxtinfo.arg); return g_wm8904info.handler(&g_wm8904info.lower, g_wm8904info.arg);
} }
/* We got an interrupt with no handler. This should not /* We got an interrupt with no handler. This should not
@@ -269,18 +288,6 @@ int sam_wm8904_initialize(int minor)
goto errout_with_i2c; goto errout_with_i2c;
} }
/* Now we can use these I2C and I2S interfaces to initialize the
* MW8904 which will return an audio interface.
*/
wm8904 = wm8904_initialize(i2c, i2s, &g_mxtinfo.lower);
if (!wm8904)
{
auddbg("Failed to initialize the WM8904\n");
ret = -ENODEV;
goto errout_with_i2s;
}
/* Configure the DAC master clock. This clock is provided by PCK2 (PB10) /* Configure the DAC master clock. This clock is provided by PCK2 (PB10)
* that is connected to the WM8904 MCLK. * that is connected to the WM8904 MCLK.
*/ */
@@ -307,7 +314,19 @@ int sam_wm8904_initialize(int minor)
if (ret < 0) if (ret < 0)
{ {
auddbg("ERROR: Failed to attach WM8904 interrupt: %d\n", ret); auddbg("ERROR: Failed to attach WM8904 interrupt: %d\n", ret);
goto errout_with_audio; goto errout_with_i2s;
}
/* Now we can use these I2C and I2S interfaces to initialize the
* MW8904 which will return an audio interface.
*/
wm8904 = wm8904_initialize(i2c, i2s, &g_wm8904info.lower);
if (!wm8904)
{
auddbg("Failed to initialize the WM8904\n");
ret = -ENODEV;
goto errout_with_irq;
} }
/* No we can embed the WM8904/I2C/I2S conglomerate into a PCM decoder /* No we can embed the WM8904/I2C/I2S conglomerate into a PCM decoder
@@ -320,7 +339,7 @@ int sam_wm8904_initialize(int minor)
{ {
auddbg("ERROR: Failed create the PCM decoder\n"); auddbg("ERROR: Failed create the PCM decoder\n");
ret = -ENODEV; ret = -ENODEV;
goto errout_with_irq; goto errout_with_wm8904;
} }
/* Create a device name */ /* Create a device name */
@@ -351,9 +370,9 @@ int sam_wm8904_initialize(int minor)
*/ */
errout_with_pcm: errout_with_pcm:
errout_with_wm8904:
errout_with_irq: errout_with_irq:
irq_detach(IRQ_INT_WM8904); irq_detach(IRQ_INT_WM8904);
errout_with_audio:
errout_with_i2s: errout_with_i2s:
errout_with_i2c: errout_with_i2c:
errout: errout: