From: Yuri R. <yu...@re...> - 2009-07-23 05:17:42
|
Yuri Roibu wrote: > > Hello everybody im new to this i have a board UCB1400,and i want to be > able to read Status of battery > from my gumstix > > and i am using "gumstix-kernel-2.6.21" > > and this is my "ucb1400-ac97-audio.patch" > > > > Index: linux-2.6.21/sound/pci/ac97/ac97_codec.c > =================================================================== > --- linux-2.6.21/sound/pci/ac97/ac97_codec.c 2008-03-19 18:10:49.000000000 > -0400 > +++ linux-2.6.21/sound/pci/ac97/ac97_codec.c 2008-03-19 18:10:09.000000000 > -0400 > @@ -158,7 +158,7 @@ > { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only > guess --jk > { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, > { 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume > wrap fix > -{ 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL }, > +{ 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL, > AC97_HAS_NO_STD_PCM }, > { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, > AC97_MODEM_PATCH }, > { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, > { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, > Index: linux-2.6.21/sound/pci/ac97/ac97_patch.c > =================================================================== > --- linux-2.6.21/sound/pci/ac97/ac97_patch.c 2008-03-19 18:11:05.000000000 > -0400 > +++ linux-2.6.21/sound/pci/ac97/ac97_patch.c 2008-02-04 17:14:41.000000000 > -0500 > @@ -29,6 +29,10 @@ > #include <linux/slab.h> > #include <linux/mutex.h> > > +#include <linux/proc_fs.h> > +#include <linux/string.h> > +#include <linux/ctype.h> > + > #include <sound/core.h> > #include <sound/pcm.h> > #include <sound/control.h> > @@ -406,6 +410,303 @@ > } > > /* > + * UCB1400 codec > + */ > + > +#define AC97_UCB1400_FCSR1 0x6a > +#define AC97_UCB1400_FCSR2 0x6c > + > +static const struct snd_kcontrol_new ucb1400_snd_ac97_controls[] = { > + AC97_SINGLE("Tone Control - Bass", AC97_UCB1400_FCSR1, 11, 4, 0), > + AC97_SINGLE("Tone Control - Treble", AC97_UCB1400_FCSR1, 9, 2, 0), > + AC97_SINGLE("Headphone Playback Switch", AC97_UCB1400_FCSR1, 6, 1, 0), > + AC97_SINGLE("De-emphasis", AC97_UCB1400_FCSR1, 5, 1, 0), > + AC97_SINGLE("DC Filter", AC97_UCB1400_FCSR1, 4, 1, 0), > + AC97_SINGLE("Hi-pass Filter", AC97_UCB1400_FCSR1, 3, 1, 0), > + AC97_SINGLE("ADC Filter", AC97_UCB1400_FCSR2, 12, 1, 0), > +}; > + > +#define NUM_GPIO_LINES 10 > +#define NUM_ADC_LINES 8 > + > +static struct proc_dir_entry *proc_gpio_parent; > +static struct proc_dir_entry *proc_gpios[NUM_GPIO_LINES]; > + > +static struct proc_dir_entry *proc_adc_parent; > +static struct proc_dir_entry *proc_adcs[NUM_ADC_LINES]; > + > +typedef struct > +{ > + int gpio; > + char name[32]; > + struct snd_ac97 *ac97; > +} gpio_summary_type; > + > +static gpio_summary_type gpio_summaries[NUM_GPIO_LINES] = > +{ > + { 0, "UCB1400-0-0" }, > + { 1, "UCB1400-0-1" }, > + { 2, "UCB1400-0-2" }, > + { 3, "UCB1400-0-3" }, > + { 4, "UCB1400-0-4" }, > + { 5, "UCB1400-0-5" }, > + { 6, "UCB1400-0-6" }, > + { 7, "UCB1400-0-7" }, > + { 8, "UCB1400-0-8" }, > + { 9, "UCB1400-0-9" } > +}; > + > +typedef struct > +{ > + int adc; > + char name[32]; > + struct snd_ac97 *ac97; > +} adc_summary_type; > + > +static adc_summary_type adc_summaries[NUM_ADC_LINES] = > +{ > + { 0, "TS-PX" }, > + { 1, "TS-MX" }, > + { 2, "TS-PY" }, > + { 3, "TS-MY" }, > + { 4, "ADC0" }, > + { 5, "ADC1" }, > + { 6, "ADC2" }, > + { 7, "ADC3" } > +}; > + > + > +static int proc_ucb1400_ac97_gpio_write(struct file *file, const char > __user *buf, > + unsigned long count, void *data) > +{ > + char *cur, lbuf[count + 1]; > + gpio_summary_type *summary = data; > + u32 direction_is_out, operation_is_set; > + int i = summary->gpio; > + u16 dir, value; > + > + if (!capable(CAP_SYS_ADMIN)) > + return -EACCES; > + > + memset(lbuf, 0, count + 1); > + > + if (copy_from_user(lbuf, buf, count)) > + return -EFAULT; > + > + cur = lbuf; > + > + // Get current values > + direction_is_out = !!(snd_ac97_read(summary->ac97, 0x5c) & (0x0001 << > i)); > + operation_is_set = !!(snd_ac97_read(summary->ac97, 0x5a) & (0x0001 << > i)); > + while(1) > + { > + // We accept options: {GPIO|AF1|AF2|AF3}, {set|clear}, > {in|out} > + // Anything else is an error > + while(cur[0] && (isspace(cur[0]) || ispunct(cur[0]))) cur = > &(cur[1]); > + > + if('\0' == cur[0]) break; > + > + // Ok, so now we're pointing at the start of something > + switch(cur[0]) > + { > + case 'G': > + // Check that next is "PIO" -- '\0' will > cause safe short-circuit if end of buf > + if(!(cur[1] == 'P' && cur[2] == 'I' && cur[3] > == 'O')) goto parse_error; > + cur = &(cur[4]); > + break; > + case 's': > + if(!(cur[1] == 'e' && cur[2] == 't')) goto > parse_error; > + operation_is_set = 1; > + cur = &(cur[3]); > + break; > + case 'c': > + if(!(cur[1] == 'l' && cur[2] == 'e' && cur[3] > == 'a' && cur[4] == 'r')) goto > +parse_error; > + operation_is_set = 0; > + cur = &(cur[5]); > + break; > + case 'i': > + if(!(cur[1] == 'n')) goto parse_error; > + direction_is_out = 0; > + cur = &(cur[2]); > + break; > + case 'o': > + if(!(cur[1] == 'u' && cur[2] == 't')) goto > parse_error; > + direction_is_out = 1; > + cur = &(cur[3]); > + break; > + default: goto parse_error; > + } > + } > + > + // set/get value > + dir = snd_ac97_read(summary->ac97, 0x5c); > + value = snd_ac97_read(summary->ac97, 0x5a); > + if (direction_is_out) > + { > + dir |= 0x0001 << i; > + if (operation_is_set) > + { > + value |= 0x0001 << i; > + } > + else > + { > + value &= ~(0x0001 << i); > + } > + > + snd_ac97_write(summary->ac97, 0x5c, dir); > + snd_ac97_write(summary->ac97, 0x5a, value); > + } > + else // direction in > + { > + dir &= ~(0x0001 << i); > + snd_ac97_write(summary->ac97, 0x5c, dir); > + operation_is_set = snd_ac97_read(summary->ac97, 0x5a) & > ~(0x0001 << i); > + } > + > +#ifdef CONFIG_PROC_GPIO_DEBUG > + printk(KERN_INFO "Set (%s,%s,%s) via /proc/gpio/%s\n", > + "GPIO", > + direction_is_out ? "out" : "in", > + operation_is_set ? "set" : "clear", > + summary->name); > +#endif > + > + return count; > + > +parse_error: > + printk(KERN_CRIT "Parse error: Expect \"GPIO|[set|clear]|[in|out] > ...\"\n"); > + return -EINVAL; > +} > + > +static int proc_ucb1400_ac97_gpio_read(char *page, char **start, off_t > off, > + int count, int *eof, void *data) > +{ > + char *p = page; > + gpio_summary_type *summary = data; > + int len, i; /*, af;*/ > + i = summary->gpio; > + > + p += sprintf(p, "%d\t%s\t%s\t%s\n", i, > + "GPIO", > + (snd_ac97_read(summary->ac97, 0x5c) & (0x0001 << i)) > ? "out" : "in", > + (snd_ac97_read(summary->ac97, 0x5a) & (0x0001 << i)) > ? "set" : "clear"); > + > + len = (p - page) - off; > + > + if(len < 0) > + { > + len = 0; > + } > + > + *eof = (len <= count) ? 1 : 0; > + *start = page + off; > + > + return len; > +} > + > +static int proc_ucb1400_ac97_adc_read(char *page, char **start, off_t > off, > + int count, int *eof, void *data) > +{ > + char *p = page; > + adc_summary_type *summary = data; > + int len, i, val = 0; /*, af;*/ > + i = summary->adc; > + > + //snd_ac97_write(summary->ac97, 0x66, 0x8000 | ((0x0000 + i) << 2)); > + snd_ac97_write(summary->ac97, 0x66, 0x8080 | ((0x0000 + i) << 2)); > + > + //printk(KERN_CRIT "wrote %x to control register\n", > snd_ac97_read(summary->ac97, 0x66)); > + > + while (1) { > + val = snd_ac97_read(summary->ac97, 0x68); > + if (val & 0x8000) > + break; > + /* yield to other processes */ > + set_current_state(TASK_INTERRUPTIBLE); > + schedule_timeout(1); > + } > + > + p += sprintf(p, "%d\n", val & 0x3ff); > + > + len = (p - page) - off; > + > + if(len < 0) > + { > + len = 0; > + } > + > + *eof = (len <= count) ? 1 : 0; > + *start = page + off; > + > + return len; > + > +} > + > +int patch_ucb1400(struct snd_ac97 * ac97) > +{ > + int err, i; > + > + proc_gpio_parent = proc_mkdir("gpio", NULL); > + if(!proc_gpio_parent) return 0; > + > + for(i=0; i < NUM_GPIO_LINES; i++) > + { > + proc_gpios[i] = create_proc_entry(gpio_summaries[i].name, 0644, > proc_gpio_parent); > + if(proc_gpios[i]) > + { > + gpio_summaries[i].ac97 = ac97; > + proc_gpios[i]->data = &gpio_summaries[i]; > + proc_gpios[i]->read_proc = proc_ucb1400_ac97_gpio_read; > + proc_gpios[i]->write_proc = proc_ucb1400_ac97_gpio_write; > + } > + } > + > + proc_adc_parent = proc_mkdir("adc", NULL); > + if(!proc_adc_parent) return 0; > + > + for(i=0; i < NUM_ADC_LINES; i++) > + { > + proc_adcs[i] = create_proc_entry(adc_summaries[i].name, 0644, > proc_adc_parent); > + if(proc_adcs[i]) > + { > + adc_summaries[i].ac97 = ac97; > + proc_adcs[i]->data = &adc_summaries[i]; > + proc_adcs[i]->read_proc = proc_ucb1400_ac97_adc_read; > + proc_adcs[i]->write_proc = NULL; > + } > + } > + > + for(i = 0; i < ARRAY_SIZE(ucb1400_snd_ac97_controls); i++) { > + if((err = snd_ctl_add(ac97->bus->card, > snd_ac97_cnew(&ucb1400_snd_ac97_controls[i], ac97))) < 0) > + return err; > + } > + > + snd_ac97_write_cache(ac97, AC97_UCB1400_FCSR1, > + (0 << 11) | // 0 base boost > + (0 << 9) | // 0 treble boost > + (0 << 7) | // Mode = flat > + (1 << 6) | // Headphones enable > + (0 << 5) | // De-emphasis disabled > + (1 << 4) | // DC filter enabled > + (1 << 3) | // Hi-pass filter enabled > + (0 << 2) | // disable interrupt signalling via GPIO_INT > + (1 << 0) // clear ADC overflow status if set > + ); > + > + snd_ac97_write_cache(ac97, AC97_UCB1400_FCSR2, > + (0 << 15) | // must be 0 > + (0 << 13) | // must be 0 > + (1 << 12) | // ADC filter enabled > + (0 << 10) | // must be 0 > + (0 << 4) | // Smart low power mode on neither Codec nor PLL > + (0 << 0) // must be 0 > + ); > + > + return 0; > +} > + > +/* > * May 2, 2003 Liam Girdwood <lia...@wo...> > * removed broken wolfson00 patch. > * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and > WM9717. > @@ -3408,41 +3709,3 @@ > ac97->res_table = lm4550_restbl; > return 0; > } > - > -/* > - * UCB1400 codec > (http://www.semiconductors.philips.com/acrobat_download/datasheets/UCB1400-02.pdf) > - */ > -static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = { > -/* enable/disable headphone driver which allows direct connection to > - stereo headphone without the use of external DC blocking > - capacitors */ > -AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0), > -/* Filter used to compensate the DC offset is added in the ADC to remove > idle > - tones from the audio band. */ > -AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0), > -/* Control smart-low-power mode feature. Allows automatic power down > - of unused blocks in the ADC analog front end and the PLL. */ > -AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0), > -}; > - > -static int patch_ucb1400_specific(struct snd_ac97 * ac97) > -{ > - int idx, err; > - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) > - if ((err = snd_ctl_add(ac97->bus->card, > snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0) > - return err; > - return 0; > -} > - > -static struct snd_ac97_build_ops patch_ucb1400_ops = { > - .build_specific = patch_ucb1400_specific, > -}; > - > -int patch_ucb1400(struct snd_ac97 * ac97) > -{ > - ac97->build_ops = &patch_ucb1400_ops; > - /* enable headphone driver and smart low power mode by default */ > - snd_ac97_write(ac97, 0x6a, 0x0050); > - snd_ac97_write(ac97, 0x6c, 0x0030); > - return 0; > -} > > > what i've done is : > > i have aded the patch to the kernel patches(replaced it with an old one) > > bitbake -c clean gumstix-kernel > > bitbake -c rebuild gumstix-kernel > > Is compiling but when i am installing on my gymstix the image it doesnt > haves "adc" folder > > the patch was working fine on my old gumstix > what i am doing wrong? > any pointers will be really helpfull im stuck for 2 weeks now :( -- View this message in context: http://www.nabble.com/ADC-Problem-NEED-HELP-tp24566872p24619379.html Sent from the Gumstix mailing list archive at Nabble.com. |