#define AK4620_DFS0 (1<<0) #define AK4620_DFS1 (1<<1) #define AK4620_CKS0 (1<<2) #define AK4620_CKS1 (1<<3) /* Clock and Format Control register */ #define AK4620_DFS_REG 0x02
/* Deem and Volume Control register */ #define AK4620_DEEMVOL_REG 0x03 #define AK4620_SMUTE (1<<7)
/* * Conversion from int value to its binary form. Used for debugging. * The output buffer must be allocated prior to calling the function.
*/ staticchar *get_binary(char *buffer, int value)
{ int i, j, pos;
pos = 0; for (i = 0; i < 4; ++i) { for (j = 0; j < 8; ++j) { if (value & (1 << (31-(i*8 + j))))
buffer[pos] = '1'; else
buffer[pos] = '0';
pos++;
} if (i < 3) {
buffer[pos] = ' ';
pos++;
}
}
buffer[pos] = '\0'; return buffer;
}
/* Writes data to external register reg, both reg and data are
* GPIO representations */ staticvoid reg_write(struct snd_ice1712 *ice, unsignedint reg, unsignedint data)
{ unsignedint tmp;
mutex_lock(&ice->gpio_mutex); /* set direction of used GPIOs*/ /* all outputs */
tmp = 0x00ffff;
ice->gpio.set_dir(ice, tmp); /* mask - writable bits */
ice->gpio.set_mask(ice, ~(tmp)); /* write the data */
tmp = ice->gpio.get_data(ice);
tmp &= ~GPIO_DATA_MASK;
tmp |= data;
ice->gpio.set_data(ice, tmp);
udelay(100); /* drop output enable */
tmp &= ~GPIO_EX_GPIOE;
ice->gpio.set_data(ice, tmp);
udelay(100); /* drop the register gpio */
tmp &= ~reg;
ice->gpio.set_data(ice, tmp);
udelay(100); /* raise the register GPIO */
tmp |= reg;
ice->gpio.set_data(ice, tmp);
udelay(100);
/* raise all data gpios */
tmp |= GPIO_DATA_MASK;
ice->gpio.set_data(ice, tmp); /* mask - immutable bits */
ice->gpio.set_mask(ice, 0xffffff); /* outputs only 8-15 */
ice->gpio.set_dir(ice, 0x00ff00);
mutex_unlock(&ice->gpio_mutex);
}
staticunsignedint qtet_get_rate(struct snd_ice1712 *ice)
{ int i; unsignedchar result;
result = get_cpld(ice) & CPLD_CKS_MASK; for (i = 0; i < ARRAY_SIZE(cks_vals); i++) if (cks_vals[i] == result) return qtet_rates[i]; return 0;
}
staticint get_cks_val(int rate)
{ int i; for (i = 0; i < ARRAY_SIZE(qtet_rates); i++) if (qtet_rates[i] == rate) return cks_vals[i]; return 0;
}
/* setting new rate */ staticvoid qtet_set_rate(struct snd_ice1712 *ice, unsignedint rate)
{ unsignedintnew; unsignedchar val; /* switching ice1724 to external clock - supplied by ext. circuits */
val = inb(ICEMT1724(ice, RATE));
outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
new = (get_cpld(ice) & ~CPLD_CKS_MASK) | get_cks_val(rate); /* switch to internal clock, drop CPLD_SYNC_SEL */ new &= ~CPLD_SYNC_SEL; /* dev_dbg(ice->card->dev, "QT - set_rate: old %x, new %x\n",
get_cpld(ice), new); */
set_cpld(ice, new);
}
staticinlineunsignedchar qtet_set_mclk(struct snd_ice1712 *ice, unsignedint rate)
{ /* no change in master clock */ return 0;
}
/* setting clock to external - SPDIF */ staticint qtet_set_spdif_clock(struct snd_ice1712 *ice, int type)
{ unsignedint old, new;
old = new = get_cpld(ice); new &= ~(CPLD_CKS_MASK | CPLD_WORD_SEL); switch (type) { case EXT_SPDIF_TYPE: new |= CPLD_EXT_SPDIF; break; case EXT_WORDCLOCK_1FS_TYPE: new |= CPLD_EXT_WORDCLOCK_1FS; break; case EXT_WORDCLOCK_256FS_TYPE: new |= CPLD_EXT_WORDCLOCK_256FS; break; default:
snd_BUG();
} if (old != new) {
set_cpld(ice, new); /* changed */ return 1;
} return 0;
}
staticint qtet_get_spdif_master_type(struct snd_ice1712 *ice)
{ unsignedint val; int result;
val = get_cpld(ice); /* checking only rate/clock-related bits */
val &= (CPLD_CKS_MASK | CPLD_WORD_SEL | CPLD_SYNC_SEL); if (!(val & CPLD_SYNC_SEL)) { /* switched to internal clock, is not any external type */
result = -1;
} else { switch (val) { case (CPLD_EXT_SPDIF):
result = EXT_SPDIF_TYPE; break; case (CPLD_EXT_WORDCLOCK_1FS):
result = EXT_WORDCLOCK_1FS_TYPE; break; case (CPLD_EXT_WORDCLOCK_256FS):
result = EXT_WORDCLOCK_256FS_TYPE; break; default: /* undefined combination of external clock setup */
snd_BUG();
result = 0;
}
} return result;
}
/* Called when ak4113 detects change in the input SPDIF stream */ staticvoid qtet_ak4113_change(struct ak4113 *ak4113, unsignedchar c0, unsignedchar c1)
{ struct snd_ice1712 *ice = ak4113->change_callback_private; int rate; if ((qtet_get_spdif_master_type(ice) == EXT_SPDIF_TYPE) &&
c1) { /* only for SPDIF master mode, rate was changed */
rate = snd_ak4113_external_rate(ak4113); /* dev_dbg(ice->card->dev, "ak4113 - input rate changed to %d\n",
rate); */
qtet_akm_set_rate_val(ice->akm, rate);
}
}
/* * If clock slaved to SPDIF-IN, setting runtime rate * to the detected external rate
*/ staticvoid qtet_spdif_in_open(struct snd_ice1712 *ice, struct snd_pcm_substream *substream)
{ struct qtet_spec *spec = ice->spec; struct snd_pcm_runtime *runtime = substream->runtime; int rate;
if (qtet_get_spdif_master_type(ice) != EXT_SPDIF_TYPE) /* not external SPDIF, no rate limitation */ return; /* only external SPDIF can detect incoming sample rate */
rate = snd_ak4113_external_rate(spec->ak4113); if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) {
runtime->hw.rate_min = rate;
runtime->hw.rate_max = rate;
}
}
/* switching ice1724 to external clock - supplied by ext. circuits */
val = inb(ICEMT1724(ice, RATE));
outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) return -ENOMEM; /* qtet is clocked by Xilinx array */
ice->hw_rates = &qtet_rates_info;
ice->is_spdif_master = qtet_is_spdif_master;
ice->get_rate = qtet_get_rate;
ice->set_rate = qtet_set_rate;
ice->set_mclk = qtet_set_mclk;
ice->set_spdif_clock = qtet_set_spdif_clock;
ice->get_spdif_master_type = qtet_get_spdif_master_type;
ice->ext_clock_names = ext_clock_names;
ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); /* since Qtet can detect correct SPDIF-in rate, all streams can be
* limited to this specific rate */
ice->spdif.ops.open = ice->pro_open = qtet_spdif_in_open;
ice->spec = spec;
/* Mute Off */ /* SCR Initialize*/ /* keep codec power down first */
set_scr(ice, SCR_PHP);
udelay(1); /* codec power up */
set_scr(ice, SCR_PHP | SCR_CODEC_PDN);
/* MCR Initialize */
set_mcr(ice, 0);
/* CPLD Initialize */
set_cpld(ice, 0);
ice->num_total_dacs = 2;
ice->num_total_adcs = 2;
ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL);
ak = ice->akm; if (!ak) return -ENOMEM; /* only one codec with two chips */
ice->akm_codecs = 1;
err = snd_ice1712_akm4xxx_init(ak, &akm_qtet_dac, NULL, ice); if (err < 0) return err;
err = snd_ak4113_create(ice->card,
qtet_ak4113_read,
qtet_ak4113_write,
ak4113_init_vals,
ice, &spec->ak4113); if (err < 0) return err; /* callback for codecs rate setting */
spec->ak4113->change_callback = qtet_ak4113_change;
spec->ak4113->change_callback_private = ice; /* AK41143 in Quartet can detect external rate correctly
* (i.e. check_flags = 0) */
spec->ak4113->check_flags = 0;
proc_init(ice);
qtet_set_rate(ice, 44100); return 0;
}
staticconstunsignedchar qtet_eeprom[] = {
[ICE_EEP2_SYSCONF] = 0x28, /* clock 256(24MHz), mpu401, 1xADC,
1xDACs, SPDIF in */
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
[ICE_EEP2_I2S] = 0x78, /* 96k, 24bit, 192k */
[ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, in, out-ext */
[ICE_EEP2_GPIO_DIR] = 0x00, /* 0-7 inputs, switched to output
only during output operations */
[ICE_EEP2_GPIO_DIR1] = 0xff, /* 8-15 outputs */
[ICE_EEP2_GPIO_DIR2] = 0x00,
[ICE_EEP2_GPIO_MASK] = 0xff, /* changed only for OUT operations */
[ICE_EEP2_GPIO_MASK1] = 0x00,
[ICE_EEP2_GPIO_MASK2] = 0xff,
[ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */
[ICE_EEP2_GPIO_STATE1] = 0x7d, /* all 1, but GPIO_CPLD_RW
and GPIO15 always zero */
[ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.