static ssize_t dsp_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { char cmd[32]; unsigned int arg1, arg2; int rc = 0; if (count >= sizeof(cmd)) return -EINVAL; if (copy_from_user(cmd, buf, count)) return -EFAULT; cmd[count] = 0; if ((count > 1) && (cmd[count-1] == '\n')) cmd[count-1] = 0; if (!strcmp(cmd, "wait-for-crash")) { while (!dsp_has_crashed) { int res; dsp_wait_count++; res = wait_event_interruptible(dsp_wait, dsp_has_crashed); if (res < 0) { dsp_wait_count--; return res; } } #if defined(CONFIG_MACH_MAHIMAHI) /* assert DSP NMI */ msm_proc_comm(PCOM_CUSTOMER_CMD1, 0, 0); msleep(250); #endif arg1 = SMEM_PC_OEM_FLUSH_ADSP6_CACHE; arg2 = 0; rc = cust_mproc_comm1(&arg1,&arg2); printk("Send SMEM_PC_OEM_FLUSH_ADSP6_CACHE done rc = %d", rc); msleep(250); } else if (!strcmp(cmd, "boom")) { q6audio_dsp_not_responding(); } else if (!strcmp(cmd, "continue-crash")) { dsp_has_crashed = 2; wake_up(&dsp_wait); } else { pr_err("[%s:%s] unknown dsp_debug command: %s\n", __MM_FILE__, __func__, cmd); } return count; }
static ssize_t q6_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct pcm *pcm = file->private_data; struct audio_client *ac; struct audio_buffer *ab; const char __user *start = buf; int xfer; int res; ac = pcm->ac; if (!ac) { res = -ENODEV; goto fail; } while (count > 0) { ab = ac->buf + ac->cpu_buf; if (ab->used) if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) { #ifdef CONFIG_EF12_BOARD printk("[SKY AUDIO] Dal timeout! maybe timeout or dsp dead.\n"); #else audio_client_dump(ac); pr_err("[%s:%s] timeout. dsp dead?\n", __MM_FILE__, __func__); q6audio_dsp_not_responding(); #endif } xfer = count; if (xfer > ab->size) xfer = ab->size; if (copy_to_user(buf, ab->data, xfer)) { res = -EFAULT; goto fail; } buf += xfer; count -= xfer; ab->used = 1; q6audio_read(ac, ab); ac->cpu_buf ^= 1; } fail: res = buf - start; return res; }
static ssize_t pcm_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { struct pcm *pcm = file->private_data; struct audio_client *ac; struct audio_buffer *ab; const char __user *start = buf; int xfer; pr_debug("[%s:%s] count = %d\n", __MM_FILE__, __func__, count); if (!pcm->ac) pcm_ioctl(file, AUDIO_START, 0); ac = pcm->ac; if (!ac) return -ENODEV; while (count > 0) { ab = ac->buf + ac->cpu_buf; if (ab->used) if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) { audio_client_dump(ac); pr_err("[%s:%s] timeout. dsp dead?\n", __MM_FILE__, __func__); q6audio_dsp_not_responding(); } pr_debug("[%s:%s] ab->data = %p, cpu_buf = %d", __MM_FILE__, __func__, ab->data, ac->cpu_buf); xfer = count; if (xfer > ab->size) xfer = ab->size; if (copy_from_user(ab->data, buf, xfer)) return -EFAULT; buf += xfer; count -= xfer; ab->used = 1; ab->actual_size = xfer; q6audio_write(ac, ab); ac->cpu_buf ^= 1; } return buf - start; }
static ssize_t q6_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct pcm *pcm = file->private_data; struct audio_client *ac; struct audio_buffer *ab; const char __user *start = buf; int xfer; int res; ac = pcm->ac; if (!ac) { res = -ENODEV; goto fail; } while (count > 0) { ab = ac->buf + ac->cpu_buf; if (ab->used) if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) { audio_client_dump(ac); pr_err("pcm_read: timeout. dsp dead?\n"); q6audio_dsp_not_responding(); } xfer = count; if (xfer > ab->size) xfer = ab->size; if (copy_to_user(buf, ab->data, xfer)) { res = -EFAULT; goto fail; } buf += xfer; count -= xfer; ab->used = 1; q6audio_read(ac, ab); ac->cpu_buf ^= 1; } fail: res = buf - start; return res; }
static int audio_ioctl(struct audio_client *ac, void *ptr, uint32_t len) { struct adsp_command_hdr *hdr = ptr; uint32_t tmp; int r; hdr->size = len - sizeof(u32); hdr->dst = AUDIO_ADDR(ac->session, 0, AUDIO_DOMAIN_DSP); hdr->src = AUDIO_ADDR(ac->session, 0, AUDIO_DOMAIN_MODEM); hdr->context = ac->session; ac->cb_status = -EBUSY; r = dal_call(ac->client, AUDIO_OP_CONTROL, 5, ptr, len, &tmp, sizeof(tmp)); if (r != 4) return -EIO; if (!wait_event_timeout(ac->wait, (ac->cb_status != -EBUSY), 5*HZ)) { dal_trace_dump(ac->client); pr_err("audio_ioctl: timeout. dsp dead?\n"); q6audio_dsp_not_responding(); } return ac->cb_status; }
struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate, uint32_t channels, uint32_t flags, uint32_t acdb_id) { int rc, retry = 5; struct audio_client *ac; if (q6audio_init()) return 0; ac = audio_client_alloc(bufsz); if (!ac) return 0; ac->flags = flags; mutex_lock(&audio_path_lock); if (ac->flags & AUDIO_FLAG_WRITE) { audio_rx_path_refcount++; if (audio_rx_path_refcount == 1) { _audio_rx_clk_enable(); #ifdef CONFIG_MSM_QDSP6_CALLREC q6_rx_path_enable(0, acdb_id); adie_rx_path_enable(acdb_id); #else audio_update_acdb(audio_rx_device_id, acdb_id); qdsp6_devchg_notify(ac_control, ADSP_AUDIO_RX_DEVICE, audio_rx_device_id); qdsp6_standby(ac_control); qdsp6_start(ac_control); #endif } } else { /* TODO: consider concurrency with voice call */ #ifdef CONFIG_MSM_QDSP6_CALLREC if (audio_tx_path_refcount > 0) { tx_clk_freq = 8000; } else { tx_clk_freq = rate; } #else tx_clk_freq = rate; #endif audio_tx_path_refcount++; if (audio_tx_path_refcount == 1) { #ifdef CONFIG_MSM_QDSP6_CALLREC tx_clk_freq = rate; #endif _audio_tx_clk_enable(); _audio_tx_path_enable(0, acdb_id); } } for (retry = 5;; retry--) { if (ac->flags & AUDIO_FLAG_WRITE) rc = audio_out_open(ac, bufsz, rate, channels); else #ifdef CONFIG_MSM_QDSP6_CALLREC rc = audio_in_open(ac, bufsz, flags, rate, channels); #else rc = audio_in_open(ac, bufsz, rate, channels); #endif if (rc == 0) break; if (retry == 0) q6audio_dsp_not_responding(); pr_err("q6audio: open pcm error %d, retrying\n", rc); msleep(1); } if (ac->flags & AUDIO_FLAG_WRITE) { if (audio_rx_path_refcount == 1) { #ifndef CONFIG_MSM_QDSP6_CALLREC adie_enable(); adie_set_path(adie, audio_rx_path_id, ADIE_PATH_RX); adie_set_path_freq_plan(adie, ADIE_PATH_RX, 48000); adie_proceed_to_stage(adie, ADIE_PATH_RX, ADIE_STAGE_DIGITAL_READY); adie_proceed_to_stage(adie, ADIE_PATH_RX, ADIE_STAGE_DIGITAL_ANALOG_READY); #endif audio_rx_analog_enable(1); } } mutex_unlock(&audio_path_lock); for (retry = 5;; retry--) { rc = audio_command(ac, ADSP_AUDIO_IOCTL_CMD_SESSION_START); if (rc == 0) break; if (retry == 0) q6audio_dsp_not_responding(); pr_err("q6audio: stream start error %d, retrying\n", rc); } if (!(ac->flags & AUDIO_FLAG_WRITE)) { ac->buf[0].used = 1; ac->buf[1].used = 1; q6audio_read(ac, &ac->buf[0]); q6audio_read(ac, &ac->buf[1]); } audio_prevent_sleep(); return ac; }
static ssize_t q6_amrnb_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct audio_client *ac; struct audio_buffer *ab; const char __user *start = buf; struct amrnb *amrnb = file->private_data; int xfer = 0; int res; mutex_lock(&amrnb->lock); ac = amrnb->audio_client; if (!ac) { res = -ENODEV; goto fail; } #if 1 while (count > xfer) { ab = ac->buf + ac->cpu_buf; if (ab->used) wait_event(ac->wait, (ab->used == 0)); xfer = ab->actual_size; if (copy_to_user(buf, ab->data, xfer)) { res = -EFAULT; goto fail; } buf += xfer; count -= xfer; ab->used = 1; q6audio_read(ac, ab); ac->cpu_buf ^= 1; } #else while (count > 0) { ab = ac->buf + ac->cpu_buf; if (ab->used) wait_event(ac->wait, (ab->used == 0)); #if 0 if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) { audio_client_dump(ac); pr_err("pcm_read: timeout. dsp dead?\n"); q6audio_dsp_not_responding(); } #endif xfer = count; if (xfer > ab->size) xfer = ab->size; if (copy_to_user(buf, ab->data, xfer)) { res = -EFAULT; goto fail; } buf += xfer; count -= xfer; ab->used = 1; q6audio_read(ac, ab); ac->cpu_buf ^= 1; } #endif res = buf - start; fail: mutex_unlock(&amrnb->lock); return res; }
int subsystem_restart(const char *subsys_name) { struct subsys_data *subsys; struct task_struct *tsk; struct restart_thread_data *data = NULL; if (!subsys_name) { pr_err("%s: Invalid subsystem name.", __func__); return -EINVAL; } pr_info("Subsystem Restart: Restart sequence requested for %s\n", subsys_name); /* List of subsystems is protected by a lock. New subsystems can * still come in. */ subsys = _find_subsystem(subsys_name); if (!subsys) { pr_warn("%s: Unregistered subsystem %s!", __func__, subsys_name); return -EINVAL; } //[email protected], 2011-09-20, [MDM BSP] for ULS display #ifdef CONFIG_LGE_SDIO_DEBUG_CH { if (strncmp("external_modem", subsys_name, 14) == 0) { uls_the_kind_of_subsys = ULS_SUBSYSTEM_MDM; } else if (strncmp("modem", subsys_name, 5) == 0) { uls_the_kind_of_subsys = ULS_SUBSYSTEM_MODEM; } else if (strncmp("lpass", subsys_name, 5) == 0) { uls_the_kind_of_subsys = ULS_SUBSYSTEM_LPASS; } else // this should not be happened. { uls_the_kind_of_subsys = ULS_SUBSYSTEM_OTHER; pr_info("%s: Unkown subsystem: Restart sequence requested for %s\n", __func__, subsys_name); } } #endif //[email protected], 2011-09-20, [MDM BSP] for ULS display if (restart_level != RESET_SOC) { data = kzalloc(sizeof(struct restart_thread_data), GFP_KERNEL); if (!data) { restart_level = RESET_SOC; pr_warn("%s: Failed to alloc restart data. Resetting.", __func__); } else { if (restart_level == RESET_SUBSYS_COUPLED || restart_level == RESET_SUBSYS_MIXED) data->coupled = 1; else data->coupled = 0; data->subsys = subsys; } } switch (restart_level) { case RESET_SUBSYS_COUPLED: case RESET_SUBSYS_MIXED: case RESET_SUBSYS_INDEPENDENT: dprintk("%s: Restarting %s [level=%d]!\n", __func__, subsys_name, restart_level); /* Let the kthread handle the actual restarting. Using a * workqueue will not work since all restart requests are * serialized and it prevents the short circuiting of * restart requests for subsystems already in a restart * sequence. */ tsk = kthread_run(subsystem_restart_thread, data, "subsystem_subsystem_restart_thread"); if (IS_ERR(tsk)) { /* [email protected] 2011-06-01 * add the error handler */ #if defined(CONFIG_LGE_ERROR_HANDLER) msm_set_restart_mode(SUB_UNAB_THD); #endif panic("%s: Unable to create thread to restart %s", __func__, subsys->name); } break; case RESET_SOC: #if 0//#ifdef CONFIG_LGE_DEBUG //[email protected] : ramdump for Q6 when Q6 crash or watchdog reset /* this code need to start a dspcrashd deamon in init.qcom.rc */ if (!strncmp("lpass", subsys_name,SUBSYS_NAME_MAX_LENGTH)) q6audio_dsp_not_responding(); #endif mutex_lock(&subsystem_list_lock); list_for_each_entry(subsys, &subsystem_list, list) if (subsys->crash_shutdown) subsys->crash_shutdown(subsys->name); mutex_unlock(&subsystem_list_lock); /* [email protected] 2011-06-01 * add the error handler */ #if defined(CONFIG_LGE_ERROR_HANDLER) msm_set_restart_mode(SUB_RESET_SOC); #endif panic("Resetting the SOC"); break; default: /* [email protected] 2011-06-01 * add the error handler */ #if defined(CONFIG_LGE_ERROR_HANDLER) msm_set_restart_mode(SUB_UNKNOWN); #endif panic("subsys-restart: Unknown restart level!\n"); break; } return 0; }
// Jagan- static ssize_t pcm_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { struct pcm *pcm = file->private_data; struct audio_client *ac; struct audio_buffer *ab; const char __user *start = buf; int xfer; #if 0 // Jagan+ if(!task_has_rt_policy(current)) { struct sched_param param = { .sched_priority = 99 }; printk(KERN_INFO "pcm_write to change to RT tid = %d\n", current->pid); if(sched_setscheduler_nocheck(current, SCHED_FIFO, ¶m )!=0) { printk(KERN_ERR "pcm_write fail to change to RT\n"); } } // Jagan- #endif if (!pcm->ac) pcm_ioctl(file, AUDIO_START, 0); ac = pcm->ac; if (!ac) return -ENODEV; while (count > 0) { ab = ac->buf + ac->cpu_buf; if (ab->used) if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) { audio_client_dump(ac); pr_err("[%s:%s] timeout. dsp dead?\n", __MM_FILE__, __func__); q6audio_dsp_not_responding(); } xfer = count; if (xfer > ab->size) xfer = ab->size; if (copy_from_user(ab->data, buf, xfer)) return -EFAULT; buf += xfer; count -= xfer; ab->used = 1; ab->actual_size = xfer; q6audio_write(ac, ab); ac->cpu_buf ^= 1; } return buf - start; } static int pcm_release(struct inode *inode, struct file *file) { struct pcm *pcm = file->private_data; if (pcm->ac) q6audio_close(pcm->ac); kfree(pcm); pr_info("[%s:%s] release\n", __MM_FILE__, __func__); // Jagan+ if (unlikely(1 == Is_first_boot_flag)) Is_first_boot_flag = 0; // Jagan- return 0; } static struct file_operations pcm_fops = { .owner = THIS_MODULE, .open = pcm_open, .write = pcm_write, .release = pcm_release, .unlocked_ioctl = pcm_ioctl, }; struct miscdevice pcm_misc = { .minor = MISC_DYNAMIC_MINOR, .name = "msm_pcm_out", .fops = &pcm_fops, }; static int __init pcm_init(void) { return misc_register(&pcm_misc); } device_initcall(pcm_init);