[alsa-devel] [PATCH 1/1] Added patch file and Makefile entry for CA0132 HDA codec
Takashi Iwai
tiwai at suse.de
Wed Jun 8 08:04:20 CEST 2011
At Tue, 7 Jun 2011 17:06:25 -0700,
Ian Minett wrote:
>
> Thank you very much for the feedback - we've modified the patch following your recommendations:
>
> - moved the patch to the alsa-kernel git tree
> - included the Kconfig change in the patch
> - tidied up the mutex calls and brought the number of access retries down.
Thanks for the updates!
The code looks almost good for merge, but just a few things. See
below.
> Any comments welcome, please let us know if anything should be changed further.
>
> Thanks,
> Ian
>
> Signed-off-by: Ian Minett <ian_minett at creativelabs.com>
Please give the changelog text to include whenever you re-submit the
patch.
> +static int chipio_write_address(struct hda_codec *codec,
> + unsigned int chip_addx)
> +{
> + unsigned int res = 0;
> + int retry = 50;
> +
> + /* send low 16 bits of the address */
> + do {
> + res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
> + HDA_SHORT_CMD_VENDOR_CHIP_IO_ADDRESS_LOW,
> + chip_addx & 0xffff);
> + retry--;
> + } while (res != HDA_STATUS_VENDOR_CHIP_IO_OK && retry);
> +
> + if (!retry)
> + return -EIO;
I'd write a helper function including this loop, e.g.
static int chipio_send(struct hda_codec *codec, unsigned int reg,
unsigned int data)
{
unsigned int res;
int retry = 50;
do {
res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, reg, data);
if (res == HDA_STATUS_VENDOR_CHIP_IO_OK)
return 0;
} while (--retry);
return -EIO;
}
This code chunk appears repeatedly in the following codes.
> +static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
> + struct ca0132_spec *spec = codec->spec;
> + long *valp = ucontrol->value.integer.value;
> + unsigned int data;
> + int err;
> +
> + /* any change? */
> + if (spec->curr_hp_switch == *valp)
> + return 0;
You need to wake up the controller/codec appropriately in the control
callback if the hardware access is needed. Call snd_hda_power_up() /
snd_hda_power_down() appropriately. In you case, call
snd_hda_power_up() at this point, and call snd_hda_power_down() at
exit of the function.
> +/*
> + * refresh widget caps that stored in cache
> + */
> +static void ca0132_refresh_widget_caps(struct hda_codec *codec)
> +{
Oh, this is a tricky part I overlooked at the previous time.
This looks like a dead code, though. Is it still needed?
> + int i;
> + hda_nid_t nid, start;
> +
> + start = nid = codec->start_nid;
> + snd_printd("ca0132_refresh_widget_caps: start_nid=%d\n", start);
> + for (i = 0; i < codec->num_nodes; i++, nid++) {
> + codec->wcaps[i] = snd_hda_param_read(codec, nid,
> + AC_PAR_AUDIO_WIDGET_CAP);
> + snd_printd("wcaps[0x%02x]=0x%x\n", i+start, codec->wcaps[i]);
Don't use snd_printd(). CONFIG_SND_DEBUG is usually turned on by most
distros, so it'd be annoying to see this at each time. Use
snd_printdd() if any.
> + }
> +}
> +static void ca0132_set_ct_ext(struct hda_codec *codec, int enable)
> +{
> + /* Set Creative extension */
> + snd_printd("SET CREATIVE EXTENSION\n");
Use snd_printdd().
> + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
> + HDA_LONG_CMD_VENDOR_CHIP_IO_CT_EXTENSIONS_ENABLE,
> + enable);
> + msleep(20);
Isn't this command needed when you recover from S3/S4 or powersave?
If yes, this should be called in the init callback instead of
patch_ca0132().
> +static void ca0132_init_chip(struct hda_codec *codec)
> +{
> + struct ca0132_spec *spec = codec->spec;
> +
> + mutex_init(&spec->chipio_mutex);
> +}
> +
> +static void ca0132_exit_chip(struct hda_codec *codec)
> +{
> + /* put any chip cleanup stuffs here. */
> +}
> +
> +static int ca0132_init(struct hda_codec *codec)
> +{
> + struct ca0132_spec *spec = codec->spec;
> + struct auto_pin_cfg *cfg = &spec->autocfg;
> + int i;
> +
> + for (i = 0; i < spec->multiout.num_dacs; i++) {
> + init_output(codec, spec->out_pins[i],
> + spec->multiout.dac_nids[i]);
> + }
> + init_output(codec, cfg->hp_pins[0], spec->hp_dac);
> + init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
> +
> + for (i = 0; i < spec->num_inputs; i++)
> + init_input(codec, spec->input_pins[i], spec->adcs[i]);
> +
> + init_input(codec, cfg->dig_in_pin, spec->dig_in);
> +
> + return 0;
> +}
> +
> +
> +static void ca0132_free(struct hda_codec *codec)
> +{
> + ca0132_exit_chip(codec);
> + kfree(codec->spec);
> +}
> +
> +static struct hda_codec_ops ca0132_patch_ops = {
> + .build_controls = ca0132_build_controls,
> + .build_pcms = ca0132_build_pcms,
> + .init = ca0132_init,
> + .free = ca0132_free,
> +};
> +
> +
> +
> +static int patch_ca0132(struct hda_codec *codec)
> +{
> + struct ca0132_spec *spec;
> +
> + snd_printd("patch_ca0132\n");
Use snd_printdd().
> + spec = kzalloc(sizeof(*spec), GFP_KERNEL);
Missing error check.
> + memset((void *)spec, 0, sizeof(*spec));
No need for cast.
thanks,
Takashi
More information about the Alsa-devel
mailing list