/* * Sensor subdevice helper functions */ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, struct fimc_sensor_info *s_info) { struct i2c_adapter *adapter; struct v4l2_subdev *sd = NULL; if (!s_info || !fmd) return NULL; adapter = i2c_get_adapter(s_info->pdata.i2c_bus_num); if (!adapter) { v4l2_warn(&fmd->v4l2_dev, "Failed to get I2C adapter %d, deferring probe\n", s_info->pdata.i2c_bus_num); return ERR_PTR(-EPROBE_DEFER); } sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter, s_info->pdata.board_info, NULL); if (IS_ERR_OR_NULL(sd)) { i2c_put_adapter(adapter); v4l2_warn(&fmd->v4l2_dev, "Failed to acquire subdev %s, deferring probe\n", s_info->pdata.board_info->type); return ERR_PTR(-EPROBE_DEFER); } v4l2_set_subdev_hostdata(sd, s_info); sd->grp_id = SENSOR_GROUP_ID; v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n", s_info->pdata.board_info->type); return sd; }
/** * fimc_md_register_platform_entities - register FIMC and CSIS media entities */ static int fimc_md_register_platform_entities(struct fimc_md *fmd) { struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; struct device_driver *driver; int ret, i; driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type); if (!driver) { v4l2_warn(&fmd->v4l2_dev, "%s driver not found, deffering probe\n", FIMC_MODULE_NAME); return -EPROBE_DEFER; } ret = driver_for_each_device(driver, NULL, fmd, fimc_register_callback); if (ret) return ret; driver = driver_find(FIMC_LITE_DRV_NAME, &platform_bus_type); if (driver && try_module_get(driver->owner)) { ret = driver_for_each_device(driver, NULL, fmd, flite_register_callback); if (ret) return ret; module_put(driver->owner); } fmd->fimc_is_subdev=fimc_is_get_subdev(); /* * Check if there is any sensor on the MIPI-CSI2 bus and * if not skip the s5p-csis module loading. */ if (pdata == NULL) return 0; for (i = 0; i < pdata->num_clients; i++) { if (pdata->isp_info[i].bus_type == FIMC_MIPI_CSI2) { ret = 1; break; } } if (!ret) return 0; driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); if (!driver || !try_module_get(driver->owner)) { v4l2_warn(&fmd->v4l2_dev, "%s driver not found, deffering probe\n", CSIS_DRIVER_NAME); return -EPROBE_DEFER; } return driver_for_each_device(driver, NULL, fmd, csis_register_callback); }
static void hmm_bo_release(struct hmm_buffer_object *bo) { struct hmm_bo_device *bdev; unsigned long flags; check_bo_null_return_void(bo); bdev = bo->bdev; /* * remove it from buffer device's buffer object list. */ spin_lock_irqsave(&bdev->list_lock, flags); list_del(&bo->list); spin_unlock_irqrestore(&bdev->list_lock, flags); /* * FIX ME: * * how to destroy the bo when it is stilled MMAPED? * * ideally, this will not happened as hmm_bo_release * will only be called when kref reaches 0, and in mmap * operation the hmm_bo_ref will eventually be called. * so, if this happened, something goes wrong. */ if (bo->status & HMM_BO_MMAPED) { v4l2_err(&atomisp_dev, "destroy bo which is MMAPED, do nothing\n"); goto err; } if (bo->status & HMM_BO_BINDED) { v4l2_warn(&atomisp_dev, "the bo is still binded, unbind it first...\n"); hmm_bo_unbind(bo); } if (bo->status & HMM_BO_PAGE_ALLOCED) { v4l2_warn(&atomisp_dev, "the pages is not freed, free pages first\n"); hmm_bo_free_pages(bo); } if (bo->status & HMM_BO_VM_ALLOCED) { v4l2_warn(&atomisp_dev, "the vm is still not freed, free vm first...\n"); hmm_bo_free_vm(bo); } if (bo->release) bo->release(bo); err: return; }
/* * use this function to initialize pre-allocated hmm_buffer_object. * as hmm_buffer_object may be used as an embedded object in an upper * level object, a release callback must be provided. if it is * embedded in upper level object, set release call back to release * function of that object. if no upper level object, set release * callback to NULL. * * bo->kref is inited to 1. */ int hmm_bo_init(struct hmm_bo_device *bdev, struct hmm_buffer_object *bo, unsigned int pgnr, void (*release) (struct hmm_buffer_object *)) { unsigned long flags; if (bdev == NULL) { v4l2_warn(&atomisp_dev, "NULL hmm_bo_device.\n"); return -EINVAL; } /* hmm_bo_device must be already inited */ var_equal_return(hmm_bo_device_inited(bdev), 0, -EINVAL, "hmm_bo_device not inited yet.\n"); /* prevent zero size buffer object */ if (pgnr == 0) { v4l2_err(&atomisp_dev, "0 size buffer is not allowed.\n"); return -EINVAL; } memset(bo, 0, sizeof(*bo)); kref_init(&bo->kref); mutex_init(&bo->mutex); INIT_LIST_HEAD(&bo->list); bo->pgnr = pgnr; bo->bdev = bdev; INIT_LIST_HEAD(&bo->pgblocks); bo->release = release; if (!bo->release) v4l2_warn(&atomisp_dev, "no release callback specified.\n"); /* * add to active_bo_list */ spin_lock_irqsave(&bdev->list_lock, flags); list_add_tail(&bo->list, &bdev->active_bo_list); bo->status |= HMM_BO_ACTIVE; spin_unlock_irqrestore(&bdev->list_lock, flags); return 0; }
static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, int num) { struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); int retval = 0, addr; if (num <= 0) return 0; mutex_lock(&dev->i2c_mutex); addr = msgs[0].addr << 1; if (num == 1) { if (msgs[0].flags & I2C_M_RD) retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0, msgs[0].buf, msgs[0].len); else retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf, msgs[0].len); } else if (num == 2) { if (msgs[0].addr != msgs[1].addr) { v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer " "with conflicting target addresses\n"); retval = -EINVAL; goto out; } if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) { v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with " "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD, msgs[1].flags & I2C_M_RD); retval = -EINVAL; goto out; } /* * Write followed by atomic read is the only complex xfer that * we actually support here. */ retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len, msgs[1].buf, msgs[1].len); } else { v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num); } out: mutex_unlock(&dev->i2c_mutex); return retval ? retval : num; }
static int camif_register_sensor(struct camif_dev *camif) { struct s3c_camif_sensor_info *sensor = &camif->pdata.sensor; struct v4l2_device *v4l2_dev = &camif->v4l2_dev; struct i2c_adapter *adapter; struct v4l2_subdev_format format; struct v4l2_subdev *sd; int ret; camif->sensor.sd = NULL; if (sensor->i2c_board_info.addr == 0) return -EINVAL; adapter = i2c_get_adapter(sensor->i2c_bus_num); if (adapter == NULL) { v4l2_warn(v4l2_dev, "failed to get I2C adapter %d\n", sensor->i2c_bus_num); return -EPROBE_DEFER; } sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &sensor->i2c_board_info, NULL); if (sd == NULL) { i2c_put_adapter(adapter); v4l2_warn(v4l2_dev, "failed to acquire subdev %s\n", sensor->i2c_board_info.type); return -EPROBE_DEFER; } camif->sensor.sd = sd; v4l2_info(v4l2_dev, "registered sensor subdevice %s\n", sd->name); /* Get initial pixel format and set it at the camif sink pad */ format.pad = 0; format.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &format); if (ret < 0) return 0; format.pad = CAMIF_SD_PAD_SINK; v4l2_subdev_call(&camif->subdev, pad, set_fmt, NULL, &format); v4l2_info(sd, "Initial format from sensor: %dx%d, %#x\n", format.format.width, format.format.height, format.format.code); return 0; }
/** * m5mols_s_power - Main sensor power control function * * To prevent breaking the lens when the sensor is powered off the Soft-Landing * algorithm is called where available. The Soft-Landing algorithm availability * dependends on the firmware provider. */ static int m5mols_s_power(struct v4l2_subdev *sd, int on) { struct m5mols_info *info = to_m5mols(sd); int ret; if (on) { ret = m5mols_sensor_power(info, true); if (!ret) ret = m5mols_fw_start(sd); return ret; } if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { ret = m5mols_set_mode(info, REG_MONITOR); if (!ret) ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP); if (!ret) ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); if (!ret) ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE, 0xff, -1); if (ret < 0) v4l2_warn(sd, "Soft landing lens failed\n"); } ret = m5mols_sensor_power(info, false); info->ctrl_sync = 0; return ret; }
/*Free L1 and L2 page table*/ void isp_mmu_exit(struct isp_mmu *mmu) { unsigned int idx; unsigned int pte; phys_addr_t l1_pt, l2_pt; if (!mmu) return; if (!ISP_PTE_VALID(mmu, mmu->l1_pte)) { v4l2_warn(&atomisp_dev, "invalid L1PT: pte = 0x%x\n", (unsigned int)mmu->l1_pte); return; } l1_pt = isp_pte_to_pgaddr(mmu, mmu->l1_pte); for (idx = 0; idx < ISP_L1PT_PTES; idx++) { pte = atomisp_get_pte(l1_pt, idx); if (ISP_PTE_VALID(mmu, pte)) { l2_pt = isp_pte_to_pgaddr(mmu, pte); free_page_table(mmu, l2_pt); } } free_page_table(mmu, l1_pt); #ifdef USE_KMEM_CACHE kmem_cache_destroy(mmu->tbl_cache); #endif }
static void imx7_csi_dma_stop(struct imx7_csi *csi) { unsigned long timeout_jiffies; unsigned long flags; int ret; /* mark next EOF interrupt as the last before stream off */ spin_lock_irqsave(&csi->irqlock, flags); csi->last_eof = true; spin_unlock_irqrestore(&csi->irqlock, flags); /* * and then wait for interrupt handler to mark completion. */ timeout_jiffies = msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT); ret = wait_for_completion_timeout(&csi->last_eof_completion, timeout_jiffies); if (ret == 0) v4l2_warn(&csi->sd, "wait last EOF timeout\n"); imx7_csi_hw_disable_irq(csi); imx7_csi_dma_unsetup_vb2_buf(csi, VB2_BUF_STATE_ERROR); imx_media_free_dma_buf(csi->dev, &csi->underrun_buf); }
/** * m5mols_s_power - Main sensor power control function * * To prevent breaking the lens when the sensor is powered off the Soft-Landing * algorithm is called where available. The Soft-Landing algorithm availability * dependends on the firmware provider. */ static int m5mols_s_power(struct v4l2_subdev *sd, int on) { struct m5mols_info *info = to_m5mols(sd); int ret; mutex_lock(&info->lock); if (on) { ret = m5mols_sensor_power(info, true); if (!ret) ret = m5mols_fw_start(sd); } else { if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { ret = m5mols_set_mode(info, REG_MONITOR); if (!ret) ret = m5mols_auto_focus_stop(info); if (ret < 0) v4l2_warn(sd, "Soft landing lens failed\n"); } ret = m5mols_sensor_power(info, false); info->ctrl_sync = 0; } mutex_unlock(&info->lock); return ret; }
/* * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS * @sdev: si4713_device structure for the device we are communicating * @usecs: timeout to wait for STC interrupt signal */ static int si4713_wait_stc(struct si4713_device *sdev, const int usecs) { int err; u8 resp[SI4713_GET_STATUS_NRESP]; /* Wait response from STC interrupt */ if (!wait_for_completion_timeout(&sdev->work, usecs_to_jiffies(usecs) + 1)) v4l2_warn(&sdev->sd, "%s: device took too much time to answer (%d usec).\n", __func__, usecs); /* Clear status bits */ err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS, NULL, 0, resp, ARRAY_SIZE(resp), DEFAULT_TIMEOUT); if (err < 0) goto exit; v4l2_dbg(1, debug, &sdev->sd, "%s: status bits: 0x%02x\n", __func__, resp[0]); if (!(resp[0] & SI4713_STC_INT)) err = -EIO; exit: return err; }
/* * si4713_send_command - sends a command to si4713 and waits its response * @sdev: si4713_device structure for the device we are communicating * @command: command id * @args: command arguments we are sending (up to 7) * @argn: actual size of @args * @response: buffer to place the expected response from the device (up to 15) * @respn: actual size of @response * @usecs: amount of time to wait before reading the response (in usecs) */ static int si4713_send_command(struct si4713_device *sdev, const u8 command, const u8 args[], const int argn, u8 response[], const int respn, const int usecs) { struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); unsigned long until_jiffies; u8 data1[MAX_ARGS + 1]; int err; if (!client->adapter) return -ENODEV; /* First send the command and its arguments */ data1[0] = command; memcpy(data1 + 1, args, argn); DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1); err = i2c_master_send(client, data1, argn + 1); if (err != argn + 1) { v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n", command); return err < 0 ? err : -EIO; } until_jiffies = jiffies + usecs_to_jiffies(usecs) + 1; /* Wait response from interrupt */ if (client->irq) { if (!wait_for_completion_timeout(&sdev->work, usecs_to_jiffies(usecs) + 1)) v4l2_warn(&sdev->sd, "(%s) Device took too much time to answer.\n", __func__); } do { err = i2c_master_recv(client, response, respn); if (err != respn) { v4l2_err(&sdev->sd, "Error %d while reading response for command 0x%02x\n", err, command); return err < 0 ? err : -EIO; } DBG_BUFFER(&sdev->sd, "Response", response, respn); if (!check_command_failed(response[0])) return 0; if (client->irq) return -EBUSY; if (usecs <= 1000) usleep_range(usecs, 1000); else usleep_range(1000, 2000); } while (time_is_after_jiffies(until_jiffies)); return -EBUSY; }
/* * set input are used to set current primary/secondary camera */ static int atomisp_s_input(struct file *file, void *fh, unsigned int input) { struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); struct v4l2_subdev *camera = NULL; int ret; if (input >= ATOM_ISP_MAX_INPUTS || input > isp->input_cnt) return -EINVAL; mutex_lock(&isp->input_lock); camera = isp->inputs[input].camera; if (!camera) { mutex_unlock(&isp->input_lock); return -EINVAL; } if ((isp->isp_subdev.video_out_vf.capq.streaming == 1) || (isp->isp_subdev.video_out_mo.capq.streaming == 1) || (isp->isp_subdev.video_in.capq.streaming == 1)) { v4l2_err(&atomisp_dev, "ISP is still streaming, stop first\n"); mutex_unlock(&isp->input_lock); return -EINVAL; } /* power off the current sensor, as it is not used this time */ if (isp->input_curr != input) { ret = v4l2_subdev_call(isp->inputs[isp->input_curr].camera, core, s_power, 0); if (ret) v4l2_warn(&atomisp_dev, "Failed to power-off sensor\n"); } /* power on the new sensor */ if (!isp->sw_contex.file_input) { ret = v4l2_subdev_call(isp->inputs[input].camera, core, s_power, 1); if (ret) { v4l2_err(&atomisp_dev, "Failed to power-on sensor\n"); mutex_unlock(&isp->input_lock); return ret; } if (isp->inputs[input].motor) ret = v4l2_subdev_call(isp->inputs[input].motor, core, init, 1); } isp->input_curr = input; mutex_unlock(&isp->input_lock); return 0; }
/* tunes the radio to the desired frequency */ static int zoltrix_s_frequency(struct radio_isa_card *isa, u32 freq) { struct zoltrix *zol = container_of(isa, struct zoltrix, isa); struct v4l2_device *v4l2_dev = &isa->v4l2_dev; unsigned long long bitmask, f, m; bool stereo = isa->stereo; int i; if (freq == 0) { v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n"); return -EINVAL; } m = (freq / 160 - 8800) * 2; f = (unsigned long long)m + 0x4d1c; bitmask = 0xc480402c10080000ull; i = 45; outb(0, isa->io); outb(0, isa->io); inb(isa->io + 3); /* Zoltrix needs to be read to confirm */ outb(0x40, isa->io); outb(0xc0, isa->io); bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); while (i--) { if ((bitmask & 0x8000000000000000ull) != 0) { outb(0x80, isa->io); udelay(50); outb(0x00, isa->io); udelay(50); outb(0x80, isa->io); udelay(50); } else { outb(0xc0, isa->io); udelay(50); outb(0x40, isa->io); udelay(50); outb(0xc0, isa->io); udelay(50); } bitmask *= 2; } /* termination sequence */ outb(0x80, isa->io); outb(0xc0, isa->io); outb(0x40, isa->io); udelay(1000); inb(isa->io + 2); udelay(1000); return zoltrix_s_mute_volume(isa, zol->muted, zol->curvol); }
/* si4713_probe - probe for the device */ static int si4713_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct si4713_device *sdev; int rval; sdev = kzalloc(sizeof *sdev, GFP_KERNEL); if (!sdev) { dev_err(&client->dev, "Failed to alloc video device.\n"); rval = -ENOMEM; goto exit; } sdev->platform_data = client->dev.platform_data; if (!sdev->platform_data) { v4l2_err(&sdev->sd, "No platform data registered.\n"); rval = -ENODEV; goto free_sdev; } v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); mutex_init(&sdev->mutex); init_completion(&sdev->work); if (client->irq) { rval = request_irq(client->irq, si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, client->name, sdev); if (rval < 0) { v4l2_err(&sdev->sd, "Could not request IRQ\n"); goto free_sdev; } v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n"); } else { v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n"); } rval = si4713_initialize(sdev); if (rval < 0) { v4l2_err(&sdev->sd, "Failed to probe device information.\n"); goto free_irq; } return 0; free_irq: if (client->irq) free_irq(client->irq, sdev); free_sdev: kfree(sdev); exit: return rval; }
/* * In case we are monitoring the first frame interval after streamon * (when fim->num_skip = 0), we need a valid fim->last_ts before we * can begin. This only applies to the input capture method. It is not * possible to accurately measure the first FI after streamon using the * EOF method, so fim->num_skip minimum is set to 1 in that case, so this * function is a noop when the EOF method is used. */ static void fim_acquire_first_ts(struct imx_media_fim *fim) { unsigned long ret; if (!fim->enabled || fim->num_skip > 0) return; ret = wait_for_completion_timeout( &fim->icap_first_event, msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT)); if (ret == 0) v4l2_warn(fim->sd, "wait first icap event timeout\n"); }
/* * Sensor subdevice helper functions */ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, struct fimc_source_info *si) { struct i2c_adapter *adapter; struct v4l2_subdev *sd = NULL; if (!si || !fmd) return NULL; /* * If FIMC bus type is not Writeback FIFO assume it is same * as sensor_bus_type. */ si->fimc_bus_type = si->sensor_bus_type; adapter = i2c_get_adapter(si->i2c_bus_num); if (!adapter) { v4l2_warn(&fmd->v4l2_dev, "Failed to get I2C adapter %d, deferring probe\n", si->i2c_bus_num); return ERR_PTR(-EPROBE_DEFER); } sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter, si->board_info, NULL); if (IS_ERR_OR_NULL(sd)) { i2c_put_adapter(adapter); v4l2_warn(&fmd->v4l2_dev, "Failed to acquire subdev %s, deferring probe\n", si->board_info->type); return ERR_PTR(-EPROBE_DEFER); } v4l2_set_subdev_hostdata(sd, si); sd->grp_id = GRP_ID_SENSOR; v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n", sd->name); return sd; }
/** * m5mols_set_mode - set the M-5MOLS controller mode * @mode: the required operation mode * * The commands of M-5MOLS are grouped into specific modes. Each functionality * can be guaranteed only when the sensor is operating in mode which a command * belongs to. */ int m5mols_set_mode(struct m5mols_info *info, u8 mode) { struct v4l2_subdev *sd = &info->sd; int ret = -EINVAL; u8 reg; if (mode < REG_PARAMETER || mode > REG_CAPTURE) return ret; ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®); if (ret || reg == mode) return ret; switch (reg) { case REG_PARAMETER: ret = m5mols_reg_mode(sd, REG_MONITOR); if (mode == REG_MONITOR) break; if (!ret) ret = m5mols_reg_mode(sd, REG_CAPTURE); break; case REG_MONITOR: if (mode == REG_PARAMETER) { ret = m5mols_reg_mode(sd, REG_PARAMETER); break; } ret = m5mols_reg_mode(sd, REG_CAPTURE); break; case REG_CAPTURE: ret = m5mols_reg_mode(sd, REG_MONITOR); if (mode == REG_MONITOR) break; if (!ret) ret = m5mols_reg_mode(sd, REG_PARAMETER); break; default: v4l2_warn(sd, "Wrong mode: %d\n", mode); } if (!ret) info->mode = mode; return ret; }
/*MMU init for internal structure*/ int isp_mmu_init(struct isp_mmu *mmu, struct isp_mmu_client *driver) { if (!mmu) /* error */ return -EINVAL; if (!driver) /* error */ return -EINVAL; if (!driver->name) v4l2_warn(&atomisp_dev, "NULL name for MMU driver...\n"); mmu->driver = driver; if (!driver->set_pd_base || !driver->tlb_flush_all) { v4l2_err(&atomisp_dev, "set_pd_base or tlb_flush_all operation " "not provided.\n"); return -EINVAL; } if (!driver->tlb_flush_range) driver->tlb_flush_range = isp_mmu_flush_tlb_range_default; if (!driver->pte_valid_mask) { v4l2_err(&atomisp_dev, "PTE_MASK is missing from mmu driver\n"); return -EINVAL; } mmu->l1_pte = driver->null_pte; mutex_init(&mmu->pt_mutex); isp_mmu_flush_tlb(mmu); #ifdef USE_KMEM_CACHE mmu->tbl_cache = kmem_cache_create("iopte_cache", ISP_PAGE_SIZE, //ISP_L1PT_PTES, SLAB_HWCACHE_ALIGN, ISP_PAGE_SIZE, SLAB_HWCACHE_ALIGN, NULL); if (!mmu->tbl_cache) return -ENOMEM; #endif return 0; }
/* * si4713_send_command - sends a command to si4713 and waits its response * @sdev: si4713_device structure for the device we are communicating * @command: command id * @args: command arguments we are sending (up to 7) * @argn: actual size of @args * @response: buffer to place the expected response from the device (up to 15) * @respn: actual size of @response * @usecs: amount of time to wait before reading the response (in usecs) */ static int si4713_send_command(struct si4713_device *sdev, const u8 command, const u8 args[], const int argn, u8 response[], const int respn, const int usecs) { struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); u8 data1[MAX_ARGS + 1]; int err; if (!client->adapter) return -ENODEV; /* First send the command and its arguments */ data1[0] = command; memcpy(data1 + 1, args, argn); DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1); err = i2c_master_send(client, data1, argn + 1); if (err != argn + 1) { v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n", command); return (err > 0) ? -EIO : err; } /* Wait response from interrupt */ if (!wait_for_completion_timeout(&sdev->work, usecs_to_jiffies(usecs) + 1)) v4l2_warn(&sdev->sd, "(%s) Device took too much time to answer.\n", __func__); /* Then get the response */ err = i2c_master_recv(client, response, respn); if (err != respn) { v4l2_err(&sdev->sd, "Error while reading response for command 0x%02x\n", command); return (err > 0) ? -EIO : err; } DBG_BUFFER(&sdev->sd, "Response", response, respn); if (check_command_failed(response[0])) return -EBUSY; return 0; }
static int imx7_csi_dma_start(struct imx7_csi *csi) { struct imx_media_video_dev *vdev = csi->vdev; struct v4l2_pix_format *out_pix = &vdev->fmt.fmt.pix; int ret; ret = imx_media_alloc_dma_buf(csi->dev, &csi->underrun_buf, out_pix->sizeimage); if (ret < 0) { v4l2_warn(&csi->sd, "consider increasing the CMA area\n"); return ret; } csi->frame_sequence = 0; csi->last_eof = false; init_completion(&csi->last_eof_completion); imx7_csi_setup_vb2_buf(csi); return 0; }
/* * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS * @sdev: si4713_device structure for the device we are communicating * @usecs: timeout to wait for STC interrupt signal */ static int si4713_wait_stc(struct si4713_device *sdev, const int usecs) { struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); u8 resp[SI4713_GET_STATUS_NRESP]; unsigned long start_jiffies = jiffies; int err; if (client->irq && !wait_for_completion_timeout(&sdev->work, usecs_to_jiffies(usecs) + 1)) v4l2_warn(&sdev->sd, "(%s) Device took too much time to answer.\n", __func__); for (;;) { /* Clear status bits */ err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS, NULL, 0, resp, ARRAY_SIZE(resp), DEFAULT_TIMEOUT); /* The USB device returns errors when it waits for the * STC bit to be set. Hence polling */ if (err >= 0) { v4l2_dbg(1, debug, &sdev->sd, "%s: status bits: 0x%02x\n", __func__, resp[0]); if (resp[0] & SI4713_STC_INT) return 0; } if (jiffies_to_usecs(jiffies - start_jiffies) > usecs) return err < 0 ? err : -EIO; /* We sleep here for 3-4 ms in order to avoid flooding the device * with USB requests. The si4713 USB driver was developed * by reverse engineering the Windows USB driver. The windows * driver also has a ~2.5 ms delay between responses. */ usleep_range(3000, 4000); } }
static int atomisp_register_entities(struct atomisp_device *isp) { int ret = 0; int i = 0; struct v4l2_subdev *subdev = NULL; struct media_entity *input = NULL; unsigned int flags; unsigned int pad; isp->media_dev.dev = isp->dev; strlcpy(isp->media_dev.model, "Intel Atom ISP", sizeof(isp->media_dev.model)); ret = media_device_register(&isp->media_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "%s: Media device registration " "failed (%d)\n", __func__, ret); return ret; } isp->v4l2_dev.mdev = &isp->media_dev; ret = v4l2_device_register(isp->dev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "%s: V4L2 device registration failed (%d)\n", __func__, ret); goto v4l2_device_failed; } /* * fixing me! * not sub device exists on * mrfld vp */ if (!IS_MRFLD) { ret = atomisp_subdev_probe(isp); if (ret < 0) goto lane4_and_subdev_probe_failed; } /* Register internal entities */ ret = atomisp_mipi_csi2_register_entities(&isp->csi2_4p, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_mipi_csi2_register_entities 4p\n"); goto lane4_and_subdev_probe_failed; } ret = atomisp_mipi_csi2_register_entities(&isp->csi2_1p, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_mipi_csi2_register_entities 1p\n"); goto lane1_failed; } ret = atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_file_input_register_entities\n"); goto file_input_register_failed; } ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n"); goto tpg_register_failed; } ret = atomisp_subdev_register_entities(&isp->isp_subdev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_subdev_register_entities fail\n"); goto subdev_register_failed; } for (i = 0; i < isp->input_cnt; i++) { subdev = isp->inputs[i].camera; switch (isp->inputs[i].port) { case ATOMISP_CAMERA_PORT_PRIMARY: input = &isp->csi2_4p.subdev.entity; pad = CSI2_PAD_SINK; flags = 0; break; case ATOMISP_CAMERA_PORT_SECONDARY: input = &isp->csi2_1p.subdev.entity; pad = CSI2_PAD_SINK; flags = 0; break; default: v4l2_dbg(1, dbg_level, &atomisp_dev, "isp->inputs type not supported\n"); break; } ret = media_entity_create_link(&subdev->entity, 0, input, pad, flags); if (ret < 0) { v4l2_err(&atomisp_dev, "snr to mipi csi link failed\n"); goto link_failed; } } v4l2_dbg(1, dbg_level, &atomisp_dev, "FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt); isp->inputs[isp->input_cnt].type = FILE_INPUT; isp->inputs[isp->input_cnt].port = -1; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd; if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { v4l2_dbg(1, dbg_level, &atomisp_dev, "TPG detected, camera_cnt: %d\n", isp->input_cnt); isp->inputs[isp->input_cnt].type = TEST_PATTERN; isp->inputs[isp->input_cnt].port = -1; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd; } else { v4l2_warn(&atomisp_dev, "too many atomisp inputs, TPG ignored.\n"); } ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev); if (ret < 0) goto link_failed; return ret; link_failed: atomisp_subdev_unregister_entities(&isp->isp_subdev); subdev_register_failed: atomisp_tpg_unregister_entities(&isp->tpg); tpg_register_failed: atomisp_file_input_unregister_entities(&isp->file_dev); file_input_register_failed: atomisp_mipi_csi2_unregister_entities(&isp->csi2_1p); lane1_failed: atomisp_mipi_csi2_unregister_entities(&isp->csi2_4p); lane4_and_subdev_probe_failed: v4l2_device_unregister(&isp->v4l2_dev); v4l2_device_failed: media_device_unregister(&isp->media_dev); return ret; }
static int atomisp_subdev_probe(struct atomisp_device *isp) { struct atomisp_platform_data *pdata = NULL; struct intel_v4l2_subdev_table *subdevs; struct v4l2_subdev *subdev = NULL; struct i2c_adapter *adapter = NULL; struct i2c_board_info *board_info; int raw_index = -1; /* * fixing me! * currently no function intel_get_v4l2_subdev_table() * defined in board specific source code */ #ifndef CONFIG_X86_MRFLD pdata = (struct atomisp_platform_data *)intel_get_v4l2_subdev_table(); #else pdata = NULL; #endif if (pdata == NULL) { v4l2_err(&atomisp_dev, "no platform data available\n"); return -ENODEV; } for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) { board_info = &subdevs->v4l2_subdev.board_info; adapter = i2c_get_adapter(subdevs->v4l2_subdev.i2c_adapter_id); if (adapter == NULL) { v4l2_err(&atomisp_dev, "Failed to find i2c adapter for subdev %s\n" , board_info->type); break; } subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter, board_info, NULL); if (subdev == NULL) { v4l2_warn(&atomisp_dev, "Subdev %s detection fail\n", board_info->type); continue; } v4l2_info(&atomisp_dev, "Subdev %s successfully register\n", board_info->type); switch (subdevs->type) { case RAW_CAMERA: raw_index = isp->input_cnt; case SOC_CAMERA: if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) { v4l2_warn(&atomisp_dev, "too many atomisp inputs, ignored\n"); break; } isp->inputs[isp->input_cnt].type = subdevs->type; isp->inputs[isp->input_cnt].port = subdevs->port; isp->inputs[isp->input_cnt].camera = subdev; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; /* * initialize the subdev frame size, then next we can * judge whether frame_size store effective value via * pixel_format. */ isp->inputs[isp->input_cnt].frame_size.pixel_format = 0; isp->input_cnt++; break; case CAMERA_MOTOR: isp->motor = subdev; break; case LED_FLASH: case XENON_FLASH: isp->flash = subdev; break; default: v4l2_dbg(1, dbg_level, &atomisp_dev, "unkonw subdev probed\n"); break; } } /* * HACK: Currently VCM belongs to primary sensor only, but correct * approach must be to acquire from platform code which sensor * owns it. */ if (isp->motor && raw_index >= 0) isp->inputs[raw_index].motor = isp->motor; /*Check camera for at least one subdev in it */ if (!isp->inputs[0].camera) { v4l2_err(&atomisp_dev, "atomisp: " "no camera attached or fail to detect\n"); return -ENODEV; } return 0; }
/* si4713_probe - probe for the device */ static int si4713_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct si4713_device *sdev; struct v4l2_ctrl_handler *hdl; struct si4713_platform_data *pdata = client->dev.platform_data; struct device_node *np = client->dev.of_node; struct radio_si4713_platform_data si4713_pdev_pdata; struct platform_device *si4713_pdev; int rval; sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL); if (!sdev) { dev_err(&client->dev, "Failed to alloc video device.\n"); rval = -ENOMEM; goto exit; } sdev->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(sdev->gpio_reset)) { rval = PTR_ERR(sdev->gpio_reset); dev_err(&client->dev, "Failed to request gpio: %d\n", rval); goto exit; } sdev->vdd = devm_regulator_get_optional(&client->dev, "vdd"); if (IS_ERR(sdev->vdd)) { rval = PTR_ERR(sdev->vdd); if (rval == -EPROBE_DEFER) goto exit; dev_dbg(&client->dev, "no vdd regulator found: %d\n", rval); sdev->vdd = NULL; } sdev->vio = devm_regulator_get_optional(&client->dev, "vio"); if (IS_ERR(sdev->vio)) { rval = PTR_ERR(sdev->vio); if (rval == -EPROBE_DEFER) goto exit; dev_dbg(&client->dev, "no vio regulator found: %d\n", rval); sdev->vio = NULL; } v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); init_completion(&sdev->work); hdl = &sdev->ctrl_handler; v4l2_ctrl_handler_init(hdl, 20); sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE); sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI); sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY); sdev->rds_compressed = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0); sdev->rds_art_head = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0); sdev->rds_stereo = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1); sdev->rds_tp = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 0); sdev->rds_ta = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0); sdev->rds_ms = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1); sdev->rds_dyn_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0); sdev->rds_alt_freqs_enable = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, 0, 1, 1, 0); sdev->rds_alt_freqs = v4l2_ctrl_new_custom(hdl, &si4713_alt_freqs_ctrl, NULL); sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION, 10, DEFAULT_RDS_DEVIATION); /* * Report step as 8. From RDS spec, psname * should be 8. But there are receivers which scroll strings * sized as 8xN. */ sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0); /* * Report step as 32 (2A block). From RDS spec, * radio text should be 32 for 2A block. But there are receivers * which scroll strings sized as 32xN. Setting default to 32. */ sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0); sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1); sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250, MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME); sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_LIMITER_DEVIATION, 0, MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV); sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1); sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1, DEFAULT_ACOMP_GAIN); sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, MIN_ACOMP_THRESHOLD, MAX_ACOMP_THRESHOLD, 1, DEFAULT_ACOMP_THRESHOLD); sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0, MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME); sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000, MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME); sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1); sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION, 10, DEFAULT_PILOT_DEVIATION); sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY, 1, DEFAULT_PILOT_FREQUENCY); sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS); sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_TUNE_POWER_LEVEL, 0, SI4713_MAX_POWER, 1, DEFAULT_POWER_LEVEL); sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, SI4713_MAX_ANTCAP, 1, 0); if (hdl->error) { rval = hdl->error; goto free_ctrls; } v4l2_ctrl_cluster(29, &sdev->mute); sdev->sd.ctrl_handler = hdl; if (client->irq) { rval = devm_request_irq(&client->dev, client->irq, si4713_handler, IRQF_TRIGGER_FALLING, client->name, sdev); if (rval < 0) { v4l2_err(&sdev->sd, "Could not request IRQ\n"); goto free_ctrls; } v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n"); } else { v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n"); } rval = si4713_initialize(sdev); if (rval < 0) { v4l2_err(&sdev->sd, "Failed to probe device information.\n"); goto free_ctrls; } if (!np && (!pdata || !pdata->is_platform_device)) return 0; si4713_pdev = platform_device_alloc("radio-si4713", -1); if (!si4713_pdev) { rval = -ENOMEM; goto put_main_pdev; } si4713_pdev_pdata.subdev = client; rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata, sizeof(si4713_pdev_pdata)); if (rval) goto put_main_pdev; rval = platform_device_add(si4713_pdev); if (rval) goto put_main_pdev; sdev->pd = si4713_pdev; return 0; put_main_pdev: platform_device_put(si4713_pdev); v4l2_device_unregister_subdev(&sdev->sd); free_ctrls: v4l2_ctrl_handler_free(hdl); exit: return rval; }
/** * vpbe_initialize() - Initialize the vpbe display controller * @vpbe_dev - vpbe device ptr * * Master frame buffer device drivers calls this to initialize vpbe * display controller. This will then registers v4l2 device and the sub * devices and sets a current encoder sub device for display. v4l2 display * device driver is the master and frame buffer display device driver is * the slave. Frame buffer display driver checks the initialized during * probe and exit if not initialized. Returns status. */ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) { struct encoder_config_info *enc_info; struct amp_config_info *amp_info; struct v4l2_subdev **enc_subdev; struct osd_state *osd_device; struct i2c_adapter *i2c_adap; int output_index; int num_encoders; int ret = 0; int err; int i; /* * v4l2 abd FBDev frame buffer devices will get the vpbe_dev pointer * from the platform device by iteration of platform drivers and * matching with device name */ if (NULL == vpbe_dev || NULL == dev) { printk(KERN_ERR "Null device pointers.\n"); return -ENODEV; } if (vpbe_dev->initialized) return 0; mutex_lock(&vpbe_dev->lock); if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) { /* We have dac clock available for platform */ vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac"); if (IS_ERR(vpbe_dev->dac_clk)) { ret = PTR_ERR(vpbe_dev->dac_clk); goto fail_mutex_unlock; } if (clk_prepare_enable(vpbe_dev->dac_clk)) { ret = -ENODEV; goto fail_mutex_unlock; } } /* first enable vpss clocks */ vpss_enable_clock(VPSS_VPBE_CLOCK, 1); /* First register a v4l2 device */ ret = v4l2_device_register(dev, &vpbe_dev->v4l2_dev); if (ret) { v4l2_err(dev->driver, "Unable to register v4l2 device.\n"); goto fail_clk_put; } v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n"); err = bus_for_each_dev(&platform_bus_type, NULL, vpbe_dev, platform_device_get); if (err < 0) return err; vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev, vpbe_dev->cfg->venc.module_name); /* register venc sub device */ if (vpbe_dev->venc == NULL) { v4l2_err(&vpbe_dev->v4l2_dev, "vpbe unable to init venc sub device\n"); ret = -ENODEV; goto fail_dev_unregister; } /* initialize osd device */ osd_device = vpbe_dev->osd_device; if (NULL != osd_device->ops.initialize) { err = osd_device->ops.initialize(osd_device); if (err) { v4l2_err(&vpbe_dev->v4l2_dev, "unable to initialize the OSD device"); err = -ENOMEM; goto fail_dev_unregister; } } /* * Register any external encoders that are configured. At index 0 we * store venc sd index. */ num_encoders = vpbe_dev->cfg->num_ext_encoders + 1; vpbe_dev->encoders = kmalloc( sizeof(struct v4l2_subdev *)*num_encoders, GFP_KERNEL); if (NULL == vpbe_dev->encoders) { v4l2_err(&vpbe_dev->v4l2_dev, "unable to allocate memory for encoders sub devices"); ret = -ENOMEM; goto fail_dev_unregister; } i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id); for (i = 0; i < (vpbe_dev->cfg->num_ext_encoders + 1); i++) { if (i == 0) { /* venc is at index 0 */ enc_subdev = &vpbe_dev->encoders[i]; *enc_subdev = vpbe_dev->venc; continue; } enc_info = &vpbe_dev->cfg->ext_encoders[i]; if (enc_info->is_i2c) { enc_subdev = &vpbe_dev->encoders[i]; *enc_subdev = v4l2_i2c_new_subdev_board( &vpbe_dev->v4l2_dev, i2c_adap, &enc_info->board_info, NULL); if (*enc_subdev) v4l2_info(&vpbe_dev->v4l2_dev, "v4l2 sub device %s registered\n", enc_info->module_name); else { v4l2_err(&vpbe_dev->v4l2_dev, "encoder %s" " failed to register", enc_info->module_name); ret = -ENODEV; goto fail_kfree_encoders; } } else v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders" " currently not supported"); } /* Add amplifier subdevice for dm365 */ if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) && vpbe_dev->cfg->amp != NULL) { amp_info = vpbe_dev->cfg->amp; if (amp_info->is_i2c) { vpbe_dev->amp = v4l2_i2c_new_subdev_board( &vpbe_dev->v4l2_dev, i2c_adap, &_info->board_info, NULL); if (!vpbe_dev->amp) { v4l2_err(&vpbe_dev->v4l2_dev, "amplifier %s failed to register", amp_info->module_name); ret = -ENODEV; goto fail_kfree_encoders; } v4l2_info(&vpbe_dev->v4l2_dev, "v4l2 sub device %s registered\n", amp_info->module_name); } else { vpbe_dev->amp = NULL; v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers" " currently not supported"); } } else { vpbe_dev->amp = NULL; } /* set the current encoder and output to that of venc by default */ vpbe_dev->current_sd_index = 0; vpbe_dev->current_out_index = 0; output_index = 0; mutex_unlock(&vpbe_dev->lock); printk(KERN_NOTICE "Setting default output to %s\n", def_output); ret = vpbe_set_default_output(vpbe_dev); if (ret) { v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default output %s", def_output); return ret; } printk(KERN_NOTICE "Setting default mode to %s\n", def_mode); ret = vpbe_set_default_mode(vpbe_dev); if (ret) { v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default mode %s", def_mode); return ret; } vpbe_dev->initialized = 1; /* TBD handling of bootargs for default output and mode */ return 0; fail_kfree_encoders: kfree(vpbe_dev->encoders); fail_dev_unregister: v4l2_device_unregister(&vpbe_dev->v4l2_dev); fail_clk_put: if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) { clk_disable_unprepare(vpbe_dev->dac_clk); clk_put(vpbe_dev->dac_clk); } fail_mutex_unlock: mutex_unlock(&vpbe_dev->lock); return ret; }
static int zol_setfreq(struct zoltrix *zol, unsigned long freq) { /* tunes the radio to the desired frequency */ struct v4l2_device *v4l2_dev = &zol->v4l2_dev; unsigned long long bitmask, f, m; unsigned int stereo = zol->stereo; int i; if (freq == 0) { v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n"); return -EINVAL; } m = (freq / 160 - 8800) * 2; f = (unsigned long long)m + 0x4d1c; bitmask = 0xc480402c10080000ull; i = 45; mutex_lock(&zol->lock); zol->curfreq = freq; outb(0, zol->io); outb(0, zol->io); inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ outb(0x40, zol->io); outb(0xc0, zol->io); bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); while (i--) { if ((bitmask & 0x8000000000000000ull) != 0) { outb(0x80, zol->io); udelay(50); outb(0x00, zol->io); udelay(50); outb(0x80, zol->io); udelay(50); } else { outb(0xc0, zol->io); udelay(50); outb(0x40, zol->io); udelay(50); outb(0xc0, zol->io); udelay(50); } bitmask *= 2; } /* termination sequence */ outb(0x80, zol->io); outb(0xc0, zol->io); outb(0x40, zol->io); udelay(1000); inb(zol->io + 2); udelay(1000); if (zol->muted) { outb(0, zol->io); outb(0, zol->io); inb(zol->io + 3); udelay(1000); } mutex_unlock(&zol->lock); if (!zol->muted) zol_setvol(zol, zol->curvol); return 0; }
/** * fimc_md_create_links - create default links between registered entities * * Parallel interface sensor entities are connected directly to FIMC capture * entities. The sensors using MIPI CSIS bus are connected through immutable * link with CSI receiver entity specified by mux_id. Any registered CSIS * entity has a link to each registered FIMC capture entity. Enabled links * are created by default between each subsequent registered sensor and * subsequent FIMC capture entity. The number of default active links is * determined by the number of available sensors or FIMC entities, * whichever is less. */ static int fimc_md_create_links(struct fimc_md *fmd) { struct v4l2_subdev *sensor, *csis; struct fimc_sensor_info *s_info; struct s5p_fimc_isp_info *pdata; struct media_entity *source, *sink; int i, j, ret = 0; u32 flags = 0; for (j = 0; j < fmd->num_sensors; j++) { if (fmd->sensor[j].subdev == NULL) { v4l2_warn(&fmd->v4l2_dev, "fmd->sensor[%d].subdev = NULL!!\n", j); continue; } sensor = fmd->sensor[j].subdev; s_info = v4l2_get_subdev_hostdata(sensor); if (!s_info) { v4l2_warn(&fmd->v4l2_dev, "(%d) fimc_sensor_info = NULL!!\n", j); continue; } pdata = &s_info->pdata; switch (pdata->bus_type) { case FIMC_ITU_601...FIMC_ITU_656: /* TODO : add ITU configuration */ break; case FIMC_MIPI_CSI2: /* 1. create link beween sensor and mipi-csi */ if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES, "Wrong CSI channel id: %d\n", pdata->mux_id)) return -EINVAL; csis = fmd->csis[pdata->mux_id].sd; if (WARN(csis == NULL, "MIPI-CSI interface specified " "but s5p-csis module is not loaded!\n")) return -EINVAL; ret = media_entity_create_link(&sensor->entity, 0, &csis->entity, CSIS_PAD_SINK, flags); if (ret) return ret; v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]", sensor->entity.name, csis->entity.name); /* 2. create link beween mipi-csi and fimc */ source = &csis->entity; for (i = 0; i < FIMC_MAX_DEVS; i++) { if (!fmd->fimc[i]) continue; /* * Some FIMC variants are not fitted with camera capture * interface. Skip creating a link from sensor for those. */ if (!fmd->fimc[i]->variant->has_cam_if) continue; sink = &fmd->fimc[i]->vid_cap.subdev.entity; ret = media_entity_create_link(source, CSIS_PAD_SOURCE, sink, FIMC_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC capture subdev entity */ ret = media_entity_call(sink, link_setup, &sink->pads[FIMC_SD_PAD_SINK], &source->pads[CSIS_PAD_SOURCE], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); } break; case FIMC_IS_WB: /* 1. create link beween sensor and mipi-csi */ if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES, "Wrong CSI channel id: %d\n", pdata->mux_id)) return -EINVAL; csis = fmd->csis[pdata->mux_id].sd; if (WARN(csis == NULL, "MIPI-CSI interface specified " "but s5p-csis module is not loaded!\n")) return -EINVAL; ret = media_entity_create_link(&sensor->entity, 0, &csis->entity, CSIS_PAD_SINK, flags); if (ret) return ret; v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]", sensor->entity.name, csis->entity.name); /* 2. create link beween mipi-csi and fimc-lite */ source = &csis->entity; sink = &fmd->fimc_lite[pdata->mux_id]->subdev.entity; ret = media_entity_create_link(source, CSIS_PAD_SOURCE, sink, FLITE_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC-LITE subdev entity */ ret = media_entity_call(sink, link_setup, &source->pads[CSIS_PAD_SOURCE], &sink->pads[FLITE_SD_PAD_SINK], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]", source->name, sink->name); /* 3. create link beween fimc-lite and fimc-is */ source = &fmd->fimc_lite[pdata->mux_id]->subdev.entity; sink = &fmd->fimc_is->isp.subdev.entity; ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE, sink, FIMC_IS_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC-IS subdev entity */ ret = media_entity_call(sink, link_setup, &source->pads[FLITE_SD_PAD_SOURCE], &sink->pads[FIMC_IS_SD_PAD_SINK], flags); v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]", source->name, sink->name); /* 4. create link beween fimc-is and fimc */ source = &fmd->fimc_is->isp.subdev.entity; for (i = 0; i < (FIMC_MAX_DEVS - 1); i++) { if (!fmd->fimc[i]) continue; /* * Some FIMC variants are not fitted with camera capture * interface. Skip creating a link from sensor for those. */ if (!fmd->fimc[i]->variant->has_cam_if) continue; sink = &fmd->fimc[i]->vid_cap.subdev.entity; ret = media_entity_create_link(source, CSIS_PAD_SOURCE, sink, FIMC_SD_PAD_SINK, flags); if (ret) return ret; /* Notify FIMC capture subdev entity */ ret = media_entity_call(sink, link_setup, &source->pads[CSIS_PAD_SOURCE], &sink->pads[FIMC_SD_PAD_SINK], flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); } break; default: v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n", pdata->bus_type); return -EINVAL; } } /* Create immutable link between each FIMC's subdev and video node */ flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED; for (i = 0; i < FIMC_MAX_DEVS; i++) { if (!fmd->fimc[i]) continue; source = &fmd->fimc[i]->vid_cap.subdev.entity; sink = &fmd->fimc[i]->vid_cap.vfd.entity; ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, sink, 0, flags); if (ret) break; v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", source->name, flags ? '=' : '-', sink->name); } return ret; }
static int atomisp_register_entities(struct atomisp_device *isp) { int ret = 0; unsigned int i; isp->media_dev.dev = isp->dev; strlcpy(isp->media_dev.model, "Intel Atom ISP", sizeof(isp->media_dev.model)); ret = media_device_register(&isp->media_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "%s: Media device registration " "failed (%d)\n", __func__, ret); return ret; } isp->v4l2_dev.mdev = &isp->media_dev; ret = v4l2_device_register(isp->dev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "%s: V4L2 device registration failed (%d)\n", __func__, ret); goto v4l2_device_failed; } ret = atomisp_subdev_probe(isp); if (ret < 0) goto csi_and_subdev_probe_failed; /* Register internal entities */ for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { ret = atomisp_mipi_csi2_register_entities(&isp->csi2_port[i], &isp->v4l2_dev); if (ret == 0) continue; /* error case */ v4l2_err(&atomisp_dev, "failed to register the CSI port: %d\n", i); /* deregister all registered CSI ports */ while (i--) atomisp_mipi_csi2_unregister_entities( &isp->csi2_port[i]); goto csi_and_subdev_probe_failed; } ret = atomisp_file_input_register_entities(&isp->file_dev, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_file_input_register_entities\n"); goto file_input_register_failed; } ret = atomisp_tpg_register_entities(&isp->tpg, &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_tpg_register_entities\n"); goto tpg_register_failed; } for (i = 0; i < isp->num_of_streams; i++) { ret = atomisp_subdev_register_entities(&isp->isp_subdev[i], &isp->v4l2_dev); if (ret < 0) { v4l2_err(&atomisp_dev, "atomisp_subdev_register_entities fail\n"); goto subdev_register_failed; } } for (i = 0; i < isp->input_cnt; i++) { if (isp->inputs[i].port >= ATOMISP_CAMERA_NR_PORTS) { v4l2_err(&atomisp_dev, "isp->inputs port %d not supported\n", isp->inputs[i].port); ret = -EINVAL; goto link_failed; } ret = media_entity_create_link( &isp->inputs[i].camera->entity, 0, &isp->csi2_port[isp->inputs[i].port].subdev.entity, CSI2_PAD_SINK, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); if (ret < 0) { dev_err(isp->dev, "link create from sensor to csi-2 receiver failed\n"); goto link_failed; } } v4l2_dbg(1, dbg_level, &atomisp_dev, "FILE_INPUT enable, camera_cnt: %d\n", isp->input_cnt); isp->inputs[isp->input_cnt].type = FILE_INPUT; isp->inputs[isp->input_cnt].port = -1; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; isp->inputs[isp->input_cnt++].camera = &isp->file_dev.sd; if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { v4l2_dbg(1, dbg_level, &atomisp_dev, "TPG detected, camera_cnt: %d\n", isp->input_cnt); isp->inputs[isp->input_cnt].type = TEST_PATTERN; isp->inputs[isp->input_cnt].port = -1; isp->inputs[isp->input_cnt].shading_table = NULL; isp->inputs[isp->input_cnt].morph_table = NULL; isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd; } else { v4l2_warn(&atomisp_dev, "too many atomisp inputs, TPG ignored.\n"); } ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev); if (ret < 0) goto link_failed; return ret; link_failed: for (i = 0; i < isp->num_of_streams; i++) atomisp_subdev_unregister_entities(&isp->isp_subdev[i]); subdev_register_failed: while (i--) atomisp_subdev_unregister_entities(&isp->isp_subdev[i]); atomisp_tpg_unregister_entities(&isp->tpg); tpg_register_failed: atomisp_file_input_unregister_entities(&isp->file_dev); file_input_register_failed: for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) atomisp_mipi_csi2_unregister_entities(&isp->csi2_port[i]); csi_and_subdev_probe_failed: v4l2_device_unregister(&isp->v4l2_dev); v4l2_device_failed: media_device_unregister(&isp->media_dev); return ret; }
/* si4713_probe - probe for the device */ static int si4713_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct si4713_device *sdev; struct si4713_platform_data *pdata = client->dev.platform_data; struct v4l2_ctrl_handler *hdl; int rval, i; sdev = kzalloc(sizeof *sdev, GFP_KERNEL); if (!sdev) { dev_err(&client->dev, "Failed to alloc video device.\n"); rval = -ENOMEM; goto exit; } sdev->gpio_reset = -1; if (pdata && gpio_is_valid(pdata->gpio_reset)) { rval = gpio_request(pdata->gpio_reset, "si4713 reset"); if (rval) { dev_err(&client->dev, "Failed to request gpio: %d\n", rval); goto free_sdev; } sdev->gpio_reset = pdata->gpio_reset; gpio_direction_output(sdev->gpio_reset, 0); } for (i = 0; i < ARRAY_SIZE(sdev->supplies); i++) sdev->supplies[i].supply = si4713_supply_names[i]; rval = regulator_bulk_get(&client->dev, ARRAY_SIZE(sdev->supplies), sdev->supplies); if (rval) { dev_err(&client->dev, "Cannot get regulators: %d\n", rval); goto free_gpio; } v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); init_completion(&sdev->work); hdl = &sdev->ctrl_handler; v4l2_ctrl_handler_init(hdl, 20); sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE); sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI); sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY); sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION, 10, DEFAULT_RDS_DEVIATION); /* * Report step as 8. From RDS spec, psname * should be 8. But there are receivers which scroll strings * sized as 8xN. */ sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0); /* * Report step as 32 (2A block). From RDS spec, * radio text should be 32 for 2A block. But there are receivers * which scroll strings sized as 32xN. Setting default to 32. */ sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0); sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1); sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250, MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME); sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_LIMITER_DEVIATION, 0, MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV); sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1); sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1, DEFAULT_ACOMP_GAIN); sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, MIN_ACOMP_THRESHOLD, MAX_ACOMP_THRESHOLD, 1, DEFAULT_ACOMP_THRESHOLD); sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0, MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME); sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000, MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME); sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1); sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION, 10, DEFAULT_PILOT_DEVIATION); sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY, 1, DEFAULT_PILOT_FREQUENCY); sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS); sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_TUNE_POWER_LEVEL, 0, 120, 1, DEFAULT_POWER_LEVEL); sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops, V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, 191, 1, 0); if (hdl->error) { rval = hdl->error; goto free_ctrls; } v4l2_ctrl_cluster(20, &sdev->mute); sdev->sd.ctrl_handler = hdl; if (client->irq) { rval = request_irq(client->irq, si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, client->name, sdev); if (rval < 0) { v4l2_err(&sdev->sd, "Could not request IRQ\n"); goto put_reg; } v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n"); } else { v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n"); } rval = si4713_initialize(sdev); if (rval < 0) { v4l2_err(&sdev->sd, "Failed to probe device information.\n"); goto free_irq; } return 0; free_irq: if (client->irq) free_irq(client->irq, sdev); free_ctrls: v4l2_ctrl_handler_free(hdl); put_reg: regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); free_gpio: if (gpio_is_valid(sdev->gpio_reset)) gpio_free(sdev->gpio_reset); free_sdev: kfree(sdev); exit: return rval; }