int msm_gemini_core_reset(uint8_t op_mode, void *base, int size) { unsigned long flags; int rc = 0; int tm = 500; /*500ms*/ memset(&fe_pingpong_buf, 0, sizeof(fe_pingpong_buf)); fe_pingpong_buf.is_fe = 1; we_pingpong_index = 0; memset(&we_pingpong_buf, 0, sizeof(we_pingpong_buf)); spin_lock_irqsave(&reset_lock, flags); reset_done_ack = 0; msm_gemini_hw_reset(base, size); spin_unlock_irqrestore(&reset_lock, flags); rc = wait_event_interruptible_timeout( reset_wait, reset_done_ack, msecs_to_jiffies(tm)); if (!reset_done_ack) { GMN_DBG("%s: reset ACK failed %d", __func__, rc); return -EBUSY; } GMN_DBG("%s: reset_done_ack rc %d", __func__, rc); spin_lock_irqsave(&reset_lock, flags); reset_done_ack = 0; spin_unlock_irqrestore(&reset_lock, flags); if (op_mode == MSM_GEMINI_MODE_REALTIME_ENCODE) { /* Nothing needed for fe buffer cfg, config we only */ msm_gemini_hw_we_buffer_cfg(1); } else { /* Nothing needed for fe buffer cfg, config we only */ msm_gemini_hw_we_buffer_cfg(0); } /* @todo wait for reset done irq */ return 0; }
int msm_gemini_platform_release(struct resource *mem, void *base, int irq, void *context) { int result; free_irq(irq, context); result = msm_camio_jpeg_clk_disable(); iounmap(base); release_mem_region(mem->start, resource_size(mem)); GMN_DBG("%s:%d] success\n", __func__, __LINE__); return result; }
inline void *msm_gemini_q_out(struct msm_gemini_q *q_p) { unsigned long flags; struct msm_gemini_q_entry *q_entry_p = NULL; void *data = NULL; GMN_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); spin_lock_irqsave(&q_p->lck, flags); if (!list_empty(&q_p->q)) { q_entry_p = list_first_entry(&q_p->q, struct msm_gemini_q_entry, list); list_del_init(&q_entry_p->list); }
int msm_gemini_platform_release(struct resource *mem, void *base, int irq, void *context) { int result; free_irq(irq, context); result = msm_camio_jpeg_clk_disable(); iounmap(base); release_mem_region(mem->start, resource_size(mem)); #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION ion_client_destroy(gemini_client); #endif GMN_DBG("%s:%d] success\n", __func__, __LINE__); return result; }
void msm_gemini_hw_region_dump(int size) { uint32_t *p; uint8_t *p8; if (size > gemini_region_size) GMN_PR_ERR("%s:%d] wrong region dump size\n", __func__, __LINE__); p = (uint32_t *) gemini_region_base; while (size >= 16) { GMN_DBG("0x%08X] %08X %08X %08X %08X\n", gemini_region_size - size, readl(p), readl(p+1), readl(p+2), readl(p+3)); p += 4; size -= 16; } if (size > 0) { uint32_t d; GMN_DBG("0x%08X] ", gemini_region_size - size); while (size >= 4) { GMN_DBG("%08X ", readl(p++)); size -= 4; } d = readl(p); p8 = (uint8_t *) &d; while (size) { GMN_DBG("%02X", *p8++); size--; } GMN_DBG("\n"); } }
uint32_t msm_gemini_hw_read(struct msm_gemini_hw_cmd *hw_cmd_p) { uint32_t *paddr; uint32_t data; paddr = gemini_region_base + hw_cmd_p->offset; data = readl(paddr); data &= hw_cmd_p->mask; GMN_DBG("%s:%d] type-%d n-%d offset-0x%4x mask-0x%8x data-0x%8x\n", __func__, __LINE__, hw_cmd_p->type, hw_cmd_p->n, hw_cmd_p->offset, hw_cmd_p->mask, data); return data; }
void *msm_gemini_core_framedone_irq(int gemini_irq_status, void *context) { struct msm_gemini_hw_buf *buf_p; GMN_DBG("%s:%d]\n", __func__, __LINE__); buf_p = msm_gemini_hw_pingpong_active_buffer(&we_pingpong_buf); if (buf_p) { buf_p->framedone_len = msm_gemini_hw_encode_output_size(); pr_err("%s:%d] framedone_len %d\n", __func__, __LINE__, buf_p->framedone_len); } return buf_p; }
void msm_gemini_hw_we_buffer_update(struct msm_gemini_hw_buf *p_input, uint8_t pingpong_index) { uint32_t n_reg_val = 0; struct msm_gemini_hw_cmd *hw_cmd_p; GMN_DBG("%s:%d] pingpong index %d", __func__, __LINE__, pingpong_index); if (pingpong_index == 0) { hw_cmd_p = &hw_cmd_we_ping_update[0]; n_reg_val = ((p_input->y_len << HWIO_JPEG_WE_Y_PING_BUFFER_CFG_WE_BUFFER_LENGTH_SHFT) & HWIO_JPEG_WE_Y_PING_BUFFER_CFG_WE_BUFFER_LENGTH_BMSK); hw_cmd_p->data = n_reg_val; msm_gemini_hw_write(hw_cmd_p++); n_reg_val = p_input->y_buffer_addr; hw_cmd_p->data = n_reg_val; msm_gemini_hw_write(hw_cmd_p++); } else if (pingpong_index == 1) { hw_cmd_p = &hw_cmd_we_pong_update[0]; n_reg_val = ((p_input->y_len << HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_WE_BUFFER_LENGTH_SHFT) & HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_WE_BUFFER_LENGTH_BMSK); hw_cmd_p->data = n_reg_val; msm_gemini_hw_write(hw_cmd_p++); n_reg_val = p_input->y_buffer_addr; hw_cmd_p->data = n_reg_val; msm_gemini_hw_write(hw_cmd_p++); } else { } return; }
void msm_gemini_hw_write(struct msm_gemini_hw_cmd *hw_cmd_p) { uint32_t *paddr; uint32_t old_data, new_data; /* type, repeat n times, offset, mask, data or pdata */ GMN_DBG("%s:%d] type-%d n-%d offset-0x%4x mask-0x%8x data-0x%8x\n", __func__, __LINE__, hw_cmd_p->type, hw_cmd_p->n, hw_cmd_p->offset, hw_cmd_p->mask, hw_cmd_p->data); paddr = gemini_region_base + hw_cmd_p->offset; if (hw_cmd_p->mask == 0xffffffff) { old_data = 0; } else { old_data = readl(paddr); old_data &= ~hw_cmd_p->mask; } new_data = hw_cmd_p->data & hw_cmd_p->mask; new_data |= old_data; writel(new_data, paddr); }
int msm_gemini_platform_init(struct platform_device *pdev, struct resource **mem, void **base, int *irq, irqreturn_t (*handler) (int, void *), void *context) { int rc = -1; int gemini_irq; struct resource *gemini_mem, *gemini_io, *gemini_irq_res; void *gemini_base; gemini_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!gemini_mem) { GMN_PR_ERR("%s: no mem resource?\n", __func__); return -ENODEV; } gemini_irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!gemini_irq_res) { GMN_PR_ERR("no irq resource?\n"); return -ENODEV; } gemini_irq = gemini_irq_res->start; gemini_io = request_mem_region(gemini_mem->start, resource_size(gemini_mem), pdev->name); if (!gemini_io) { GMN_PR_ERR("%s: region already claimed\n", __func__); return -EBUSY; } gemini_base = ioremap(gemini_mem->start, resource_size(gemini_mem)); if (!gemini_base) { rc = -ENOMEM; GMN_PR_ERR("%s: ioremap failed\n", __func__); goto fail1; } rc = msm_camio_jpeg_clk_enable(); if (rc) { GMN_PR_ERR("%s: clk failed rc = %d\n", __func__, rc); goto fail2; } msm_gemini_hw_init(gemini_base, resource_size(gemini_mem)); rc = request_irq(gemini_irq, handler, IRQF_TRIGGER_RISING, "gemini", context); if (rc) { GMN_PR_ERR("%s: request_irq failed, %d, JPEG = %d\n", __func__, gemini_irq, INT_JPEG); goto fail3; } *mem = gemini_mem; *base = gemini_base; *irq = gemini_irq; GMN_DBG("%s:%d] success\n", __func__, __LINE__); return rc; fail3: msm_camio_jpeg_clk_disable(); fail2: iounmap(gemini_base); fail1: release_mem_region(gemini_mem->start, resource_size(gemini_mem)); GMN_DBG("%s:%d] fail\n", __func__, __LINE__); return rc; }
static int msm_gemini_init(struct platform_device *pdev) { int rc = -1; struct device *dev; GMN_DBG("%s:%d]\n", __func__, __LINE__); msm_gemini_device_p = __msm_gemini_init(pdev); if (msm_gemini_device_p == NULL) { GMN_PR_ERR("%s: initialization failed\n", __func__); goto fail; } rc = alloc_chrdev_region(&msm_gemini_devno, 0, 1, MSM_GEMINI_NAME); if (rc < 0) { GMN_PR_ERR("%s: failed to allocate chrdev\n", __func__); goto fail_1; } if (!msm_gemini_class) { msm_gemini_class = class_create(THIS_MODULE, MSM_GEMINI_NAME); if (IS_ERR(msm_gemini_class)) { rc = PTR_ERR(msm_gemini_class); GMN_PR_ERR("%s: create device class failed\n", __func__); goto fail_2; } } dev = device_create(msm_gemini_class, NULL, MKDEV(MAJOR(msm_gemini_devno), MINOR(msm_gemini_devno)), NULL, "%s%d", MSM_GEMINI_NAME, 0); if (IS_ERR(dev)) { GMN_PR_ERR("%s: error creating device\n", __func__); rc = -ENODEV; goto fail_3; } cdev_init(&msm_gemini_device_p->cdev, &msm_gemini_fops); msm_gemini_device_p->cdev.owner = THIS_MODULE; msm_gemini_device_p->cdev.ops = (const struct file_operations *) &msm_gemini_fops; rc = cdev_add(&msm_gemini_device_p->cdev, msm_gemini_devno, 1); if (rc < 0) { GMN_PR_ERR("%s: error adding cdev\n", __func__); rc = -ENODEV; goto fail_4; } pr_info("[CAM] %s %s: success\n", __func__, MSM_GEMINI_NAME); return rc; fail_4: device_destroy(msm_gemini_class, msm_gemini_devno); fail_3: class_destroy(msm_gemini_class); fail_2: unregister_chrdev_region(msm_gemini_devno, 1); fail_1: __msm_gemini_exit(msm_gemini_device_p); fail: return rc; }
int msm_gemini_platform_init(struct platform_device *pdev, struct resource **mem, void **base, int *irq, irqreturn_t (*handler) (int, void *), void *context) { int rc = -1; int gemini_irq; struct resource *gemini_mem, *gemini_io, *gemini_irq_res; void *gemini_base; struct msm_gemini_device *pgmn_dev = (struct msm_gemini_device *) context; gemini_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!gemini_mem) { GMN_PR_ERR("%s: no mem resource?\n", __func__); return -ENODEV; } gemini_irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!gemini_irq_res) { GMN_PR_ERR("no irq resource?\n"); return -ENODEV; } gemini_irq = gemini_irq_res->start; gemini_io = request_mem_region(gemini_mem->start, resource_size(gemini_mem), pdev->name); if (!gemini_io) { GMN_PR_ERR("%s: region already claimed\n", __func__); return -EBUSY; } gemini_base = ioremap(gemini_mem->start, resource_size(gemini_mem)); if (!gemini_base) { rc = -ENOMEM; GMN_PR_ERR("%s: ioremap failed\n", __func__); goto fail1; } pgmn_dev->hw_version = GEMINI_8X60; rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info, pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 1); if (rc < 0) { pgmn_dev->hw_version = GEMINI_7X; rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_7x_clk_info, pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_7x_clk_info), 1); if (rc < 0) { GMN_PR_ERR("%s: clk failed rc = %d\n", __func__, rc); goto fail2; } } else { rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_imem_clk_info, &pgmn_dev->gemini_clk[2], ARRAY_SIZE(gemini_imem_clk_info), 1); if (!rc) pgmn_dev->hw_version = GEMINI_8960; } if (pgmn_dev->hw_version != GEMINI_7X) { if (pgmn_dev->gemini_fs == NULL) { pgmn_dev->gemini_fs = regulator_get(&pgmn_dev->pdev->dev, "vdd"); if (IS_ERR(pgmn_dev->gemini_fs)) { pr_err("%s: Regulator FS_ijpeg get failed %ld\n", __func__, PTR_ERR(pgmn_dev->gemini_fs)); pgmn_dev->gemini_fs = NULL; goto gemini_fs_failed; } else if (regulator_enable(pgmn_dev->gemini_fs)) { pr_err("%s: Regulator FS_ijpeg enable failed\n", __func__); regulator_put(pgmn_dev->gemini_fs); pgmn_dev->gemini_fs = NULL; goto gemini_fs_failed; } } } msm_gemini_hw_init(gemini_base, resource_size(gemini_mem)); rc = request_irq(gemini_irq, handler, IRQF_TRIGGER_RISING, "gemini", context); if (rc) { GMN_PR_ERR("%s: request_irq failed, %d\n", __func__, gemini_irq); goto fail3; } *mem = gemini_mem; *base = gemini_base; *irq = gemini_irq; #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION gemini_client = msm_ion_client_create(-1, "camera/gemini"); #endif GMN_DBG("%s:%d] success\n", __func__, __LINE__); return rc; fail3: if (pgmn_dev->hw_version != GEMINI_7X) { regulator_disable(pgmn_dev->gemini_fs); regulator_put(pgmn_dev->gemini_fs); pgmn_dev->gemini_fs = NULL; } gemini_fs_failed: if (pgmn_dev->hw_version == GEMINI_8960) msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_imem_clk_info, &pgmn_dev->gemini_clk[2], ARRAY_SIZE(gemini_imem_clk_info), 0); if (pgmn_dev->hw_version != GEMINI_7X) msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info, pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 0); else msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_7x_clk_info, pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_7x_clk_info), 0); fail2: iounmap(gemini_base); fail1: release_mem_region(gemini_mem->start, resource_size(gemini_mem)); GMN_DBG("%s:%d] fail\n", __func__, __LINE__); return rc; }
irqreturn_t msm_gemini_core_irq(int irq_num, void *context) { void *data = NULL; unsigned long flags; int gemini_irq_status; GMN_DBG("%s:%d] irq_num = %d\n", __func__, __LINE__, irq_num); spin_lock_irqsave(&reset_lock, flags); reset_done_ack = 1; spin_unlock_irqrestore(&reset_lock, flags); gemini_irq_status = msm_gemini_hw_irq_get_status(); GMN_DBG("%s:%d] gemini_irq_status = %0x\n", __func__, __LINE__, gemini_irq_status); /*For reset and framedone IRQs, clear all bits*/ if (gemini_irq_status & 0x400) { wake_up(&reset_wait); msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK, JPEG_IRQ_CLEAR_ALL); } else if (gemini_irq_status & 0x1) { msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK, JPEG_IRQ_CLEAR_ALL); } else { msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK, gemini_irq_status); } if (msm_gemini_hw_irq_is_frame_done(gemini_irq_status)) { data = msm_gemini_core_framedone_irq(gemini_irq_status, context); if (msm_gemini_irq_handler) msm_gemini_irq_handler( MSM_GEMINI_HW_MASK_COMP_FRAMEDONE, context, data); } if (msm_gemini_hw_irq_is_fe_pingpong(gemini_irq_status)) { data = msm_gemini_core_fe_pingpong_irq(gemini_irq_status, context); if (msm_gemini_irq_handler) msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_FE, context, data); } if (msm_gemini_hw_irq_is_we_pingpong(gemini_irq_status) && !msm_gemini_hw_irq_is_frame_done(gemini_irq_status)) { data = msm_gemini_core_we_pingpong_irq(gemini_irq_status, context); if (msm_gemini_irq_handler) msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_WE, context, data); } if (msm_gemini_hw_irq_is_reset_ack(gemini_irq_status)) { data = msm_gemini_core_reset_ack_irq(gemini_irq_status, context); if (msm_gemini_irq_handler) msm_gemini_irq_handler( MSM_GEMINI_HW_MASK_COMP_RESET_ACK, context, data); } /* Unexpected/unintended HW interrupt */ if (msm_gemini_hw_irq_is_err(gemini_irq_status)) { data = msm_gemini_core_err_irq(gemini_irq_status, context); if (msm_gemini_irq_handler) msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_ERR, context, data); } return IRQ_HANDLED; }
void *msm_gemini_core_reset_ack_irq(int gemini_irq_status, void *context) { /* @todo return the status back to msm_gemini_core_reset */ GMN_DBG("%s:%d]\n", __func__, __LINE__); return NULL; }
void *msm_gemini_core_we_pingpong_irq(int gemini_irq_status, void *context) { GMN_DBG("%s:%d]\n", __func__, __LINE__); return msm_gemini_hw_pingpong_irq(&we_pingpong_buf); }
int msm_gemini_platform_clk_enable(void) { /* MP*fps*(1 + %blanking) 2MP: 24MHz ------ 2 x 10 x 1.2 3MP: 36MHz ------ 3 x 10 x 1.2 5MP: 60MHz ------ 5 x 10 x 1.2 8MP: 96MHz ------ 8 x 10 x 1.2 12MP: 144MHz ------12 x 10 x 1.2 */ int rc = -1; u32 rate = 144000000; if (jpeg_clk == NULL) { jpeg_clk = clk_get(NULL, "jpeg_clk"); if (jpeg_clk == NULL) { GMN_PR_ERR("%s:%d] fail rc = %d\n", __func__, __LINE__, rc); goto fail; } } rc = clk_set_min_rate(jpeg_clk, rate); if (rc) { GMN_PR_ERR("%s:%d] fail rc = %d\n", __func__, __LINE__, rc); goto fail; } rc = clk_enable(jpeg_clk); if (rc) { GMN_PR_ERR("%s:%d] fail rc = %d\n", __func__, __LINE__, rc); goto fail; } if (jpeg_pclk == NULL) { jpeg_pclk = clk_get(NULL, "jpeg_pclk"); if (jpeg_pclk == NULL) { GMN_PR_ERR("%s:%d] fail rc = %d\n", __func__, __LINE__, rc); goto fail; } } rc = clk_enable(jpeg_pclk); if (rc) { GMN_PR_ERR("%s:%d] fail rc = %d\n", __func__, __LINE__, rc); goto fail; } rc = pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ, "msm_gemini", MSM_SYSTEM_BUS_RATE); if (rc) { GMN_PR_ERR("request AXI bus QOS fails. rc = %d\n", rc); goto fail; } GMN_DBG("%s:%d]\n", __func__, __LINE__); return rc; fail: GMN_PR_ERR("%s:%d] fail rc = %d\n", __func__, __LINE__, rc); return rc; }