Esempio n. 1
0
static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
				  struct nameidata *nd)
{
	int err;
	struct fuse_entry_out outarg;
	struct inode *inode = NULL;
#if !defined(FUSE_MAINLINE) && defined(KERNEL_2_6)
	struct dentry *newent;
#endif
	struct fuse_conn *fc = get_fuse_conn(dir);
	struct fuse_req *req;

	if (entry->d_name.len > FUSE_NAME_MAX)
		return ERR_PTR(-ENAMETOOLONG);

	req = fuse_get_request(fc);
	if (!req)
		return ERR_PTR(-EINTR);

	fuse_lookup_init(req, dir, entry, &outarg);
	request_send(fc, req);
	err = req->out.h.error;
	/* Zero nodeid is same as -ENOENT, but with valid timeout */
	if (!err && outarg.nodeid &&
	    (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode)))
		err = -EIO;
	if (!err && outarg.nodeid) {
		inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
				  &outarg.attr);
		if (!inode) {
			fuse_send_forget(fc, req, outarg.nodeid, 1);
			return ERR_PTR(-ENOMEM);
		}
	}
	fuse_put_request(fc, req);
	if (err && err != -ENOENT)
		return ERR_PTR(err);

	if (inode && dir_alias(inode)) {
		iput(inode);
		return ERR_PTR(-EIO);
	}
#if defined(FUSE_MAINLINE) || !defined(KERNEL_2_6)
	d_add(entry, inode);
#else
	newent = d_splice_alias(inode, entry);
	entry = newent ? newent : entry;
#endif
	entry->d_op = &fuse_dentry_operations;
	if (!err)
		fuse_change_timeout(entry, &outarg);
	else
		fuse_invalidate_entry_cache(entry);
#if defined(FUSE_MAINLINE) || !defined(KERNEL_2_6)
	return NULL;
#else
	return newent;
#endif
}
Esempio n. 2
0
static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
				  struct nameidata *nd)
{
	int err;
	struct fuse_entry_out outarg;
	struct inode *inode = NULL;
	struct fuse_conn *fc = get_fuse_conn(dir);
	struct fuse_req *req;
	struct fuse_req *forget_req;

	if (entry->d_name.len > FUSE_NAME_MAX)
		return ERR_PTR(-ENAMETOOLONG);

	req = fuse_get_req(fc);
	if (IS_ERR(req))
		return ERR_PTR(PTR_ERR(req));

	forget_req = fuse_get_req(fc);
	if (IS_ERR(forget_req)) {
		fuse_put_request(fc, req);
		return ERR_PTR(PTR_ERR(forget_req));
	}

	fuse_lookup_init(req, dir, entry, &outarg);
	request_send(fc, req);
	err = req->out.h.error;
	fuse_put_request(fc, req);
	/* Zero nodeid is same as -ENOENT, but with valid timeout */
	if (!err && outarg.nodeid &&
	    (invalid_nodeid(outarg.nodeid) || !valid_mode(outarg.attr.mode)))
		err = -EIO;
	if (!err && outarg.nodeid) {
		inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
				  &outarg.attr);
		if (!inode) {
			fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
			return ERR_PTR(-ENOMEM);
		}
	}
	fuse_put_request(fc, forget_req);
	if (err && err != -ENOENT)
		return ERR_PTR(err);

	if (inode && dir_alias(inode)) {
		iput(inode);
		return ERR_PTR(-EIO);
	}
	d_add(entry, inode);
	entry->d_op = &fuse_dentry_operations;
	if (!err)
		fuse_change_timeout(entry, &outarg);
	else
		fuse_invalidate_entry_cache(entry);
	return NULL;
}
Esempio n. 3
0
/*
 * V4L2 - Handles VIDIOC_S_FMT Ioctl
 *
 * @param vout         structure vout_data *
 *
 * @param v4l2_format structure v4l2_format *
 *
 * @return  status    0 success, EINVAL failed
 */
static int mxc_v4l2out_s_fmt(vout_data * vout, struct v4l2_format *f)
{
	int retval = 0;
	u32 size = 0;
	u32 bytesperline;

	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		retval = -EINVAL;
		goto err0;
	}
	if (!valid_mode(f->fmt.pix.pixelformat)) {
		DPRINTK("pixel format not supported\n");
		retval = -EINVAL;
		goto err0;
	}

	bytesperline = (f->fmt.pix.width * fmt_to_bpp(f->fmt.pix.pixelformat)) /
	    8;
	if (f->fmt.pix.bytesperline < bytesperline) {
		f->fmt.pix.bytesperline = bytesperline;
	} else {
		bytesperline = f->fmt.pix.bytesperline;
	}

	switch (f->fmt.pix.pixelformat) {
	case V4L2_PIX_FMT_YUV422P:
		/* byteperline for YUV planar formats is for
		   Y plane only */
		size = bytesperline * f->fmt.pix.height * 2;
		break;
	case V4L2_PIX_FMT_YUV420:
		size = (bytesperline * f->fmt.pix.height * 3) / 2;
		break;
	default:
		size = bytesperline * f->fmt.pix.height;
		break;
	}

	/* Return the actual size of the image to the app */
	f->fmt.pix.sizeimage = size;

	vout->v2f.fmt.pix.sizeimage = size;
	vout->v2f.fmt.pix.width = f->fmt.pix.width;
	vout->v2f.fmt.pix.height = f->fmt.pix.height;
	vout->v2f.fmt.pix.pixelformat = f->fmt.pix.pixelformat;
	vout->v2f.fmt.pix.bytesperline = f->fmt.pix.bytesperline;

	retval = 0;
      err0:
	return retval;
}
Esempio n. 4
0
static int ldb_disp_init(struct mxc_dispdrv_handle *disp,
	struct mxc_dispdrv_setting *setting)
{
	int ret = 0, i;
	struct ldb_data *ldb = mxc_dispdrv_getdata(disp);
	struct fsl_mxc_ldb_platform_data *plat_data = ldb->pdev->dev.platform_data;
	struct resource *res;
	uint32_t base_addr;
	uint32_t reg, setting_idx;
	uint32_t ch_mask = 0, ch_val = 0;
	uint32_t ipu_id, disp_id;

	/* if input format not valid, make RGB666 as default*/
	if (!valid_mode(setting->if_fmt)) {
		dev_warn(&ldb->pdev->dev, "Input pixel format not valid"
					" use default RGB666\n");
		setting->if_fmt = IPU_PIX_FMT_RGB666;
	}

	if (!ldb->inited) {
		char di_clk[] = "ipu1_di0_clk";
		char ldb_clk[] = "ldb_di0_clk";
		int lvds_channel = 0;

		setting_idx = 0;
		res = platform_get_resource(ldb->pdev, IORESOURCE_MEM, 0);
		if (IS_ERR(res))
			return -ENOMEM;

		base_addr = res->start;
		ldb->reg = ioremap(base_addr, res->end - res->start + 1);
		ldb->control_reg = ldb->reg + 2;
		ldb->gpr3_reg = ldb->reg + 3;

		ldb->lvds_bg_reg = regulator_get(&ldb->pdev->dev, plat_data->lvds_bg_reg);
		if (!IS_ERR(ldb->lvds_bg_reg)) {
			regulator_set_voltage(ldb->lvds_bg_reg, 2500000, 2500000);
			regulator_enable(ldb->lvds_bg_reg);
		}

		/* ipu selected by platform data setting */
		setting->dev_id = plat_data->ipu_id;

		reg = readl(ldb->control_reg);

		/* refrence resistor select */
		reg &= ~LDB_BGREF_RMODE_MASK;
		if (plat_data->ext_ref)
			reg |= LDB_BGREF_RMODE_EXT;
		else
			reg |= LDB_BGREF_RMODE_INT;

		/* TODO: now only use SPWG data mapping for both channel */
		reg &= ~(LDB_BIT_MAP_CH0_MASK | LDB_BIT_MAP_CH1_MASK);
		reg |= LDB_BIT_MAP_CH0_SPWG | LDB_BIT_MAP_CH1_SPWG;

		/* channel mode setting */
		reg &= ~(LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
		reg &= ~(LDB_DATA_WIDTH_CH0_MASK | LDB_DATA_WIDTH_CH1_MASK);

		if (bits_per_pixel(setting->if_fmt) == 24)
			reg |= LDB_DATA_WIDTH_CH0_24 | LDB_DATA_WIDTH_CH1_24;
		else
			reg |= LDB_DATA_WIDTH_CH0_18 | LDB_DATA_WIDTH_CH1_18;

		if (g_ldb_mode)
			ldb->mode = g_ldb_mode;
		else
			ldb->mode = plat_data->mode;

		if ((ldb->mode == LDB_SIN0) || (ldb->mode == LDB_SIN1)) {
			ret = ldb->mode - LDB_SIN0;
			if (plat_data->disp_id != ret) {
				dev_warn(&ldb->pdev->dev,
					"change IPU DI%d to IPU DI%d for LDB "
					"channel%d.\n",
					plat_data->disp_id, ret, ret);
				plat_data->disp_id = ret;
			}
		} else if (((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1))
				&& (cpu_is_mx6q() || cpu_is_mx6dl())) {
			if (plat_data->disp_id == plat_data->sec_disp_id) {
				dev_err(&ldb->pdev->dev,
					"For LVDS separate mode,"
					"two DIs should be different!\n");
				return -EINVAL;
			}

			if (((!plat_data->disp_id) && (ldb->mode == LDB_SEP1))
				|| ((plat_data->disp_id) &&
					(ldb->mode == LDB_SEP0))) {
				dev_dbg(&ldb->pdev->dev,
					"LVDS separate mode:"
					"swap DI configuration!\n");
				ipu_id = plat_data->ipu_id;
				disp_id = plat_data->disp_id;
				plat_data->ipu_id = plat_data->sec_ipu_id;
				plat_data->disp_id = plat_data->sec_disp_id;
				plat_data->sec_ipu_id = ipu_id;
				plat_data->sec_disp_id = disp_id;
			}
		}

		if (ldb->mode == LDB_SPL_DI0) {
			reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI0
				| LDB_CH1_MODE_EN_TO_DI0;
			setting->disp_id = 0;
		} else if (ldb->mode == LDB_SPL_DI1) {
			reg |= LDB_SPLIT_MODE_EN | LDB_CH0_MODE_EN_TO_DI1
				| LDB_CH1_MODE_EN_TO_DI1;
			setting->disp_id = 1;
		} else if (ldb->mode == LDB_DUL_DI0) {
			reg &= ~LDB_SPLIT_MODE_EN;
			reg |= LDB_CH0_MODE_EN_TO_DI0 | LDB_CH1_MODE_EN_TO_DI0;
			setting->disp_id = 0;
		} else if (ldb->mode == LDB_DUL_DI1) {
			reg &= ~LDB_SPLIT_MODE_EN;
			reg |= LDB_CH0_MODE_EN_TO_DI1 | LDB_CH1_MODE_EN_TO_DI1;
			setting->disp_id = 1;
		} else if (ldb->mode == LDB_SIN0) {
			reg &= ~LDB_SPLIT_MODE_EN;
			setting->disp_id = plat_data->disp_id;
			if (setting->disp_id == 0)
				reg |= LDB_CH0_MODE_EN_TO_DI0;
			else
				reg |= LDB_CH0_MODE_EN_TO_DI1;
			ch_mask = LDB_CH0_MODE_MASK;
			ch_val = reg & LDB_CH0_MODE_MASK;
		} else if (ldb->mode == LDB_SIN1) {
			reg &= ~LDB_SPLIT_MODE_EN;
			setting->disp_id = plat_data->disp_id;
			if (setting->disp_id == 0)
				reg |= LDB_CH1_MODE_EN_TO_DI0;
			else
				reg |= LDB_CH1_MODE_EN_TO_DI1;
			ch_mask = LDB_CH1_MODE_MASK;
			ch_val = reg & LDB_CH1_MODE_MASK;
		} else { /* separate mode*/
			setting->disp_id = plat_data->disp_id;

			/* first output is LVDS0 or LVDS1 */
			if (ldb->mode == LDB_SEP0)
				lvds_channel = 0;
			else
				lvds_channel = 1;

			reg &= ~LDB_SPLIT_MODE_EN;

			if ((lvds_channel == 0) && (setting->disp_id == 0))
				reg |= LDB_CH0_MODE_EN_TO_DI0;
			else if ((lvds_channel == 0) && (setting->disp_id == 1))
				reg |= LDB_CH0_MODE_EN_TO_DI1;
			else if ((lvds_channel == 1) && (setting->disp_id == 0))
				reg |= LDB_CH1_MODE_EN_TO_DI0;
			else
				reg |= LDB_CH1_MODE_EN_TO_DI1;
			ch_mask = lvds_channel ? LDB_CH1_MODE_MASK :
					LDB_CH0_MODE_MASK;
			ch_val = reg & ch_mask;

			if (bits_per_pixel(setting->if_fmt) == 24) {
				if (lvds_channel == 0)
					reg &= ~LDB_DATA_WIDTH_CH1_24;
				else
					reg &= ~LDB_DATA_WIDTH_CH0_24;
			} else {
				if (lvds_channel == 0)
					reg &= ~LDB_DATA_WIDTH_CH1_18;
				else
					reg &= ~LDB_DATA_WIDTH_CH0_18;
			}
		}

		writel(reg, ldb->control_reg);
		if (ldb->mode <  LDB_SIN0) {
			ch_mask = LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK;
			ch_val = reg & (LDB_CH0_MODE_MASK | LDB_CH1_MODE_MASK);
		}

		/* clock setting */
		if ((cpu_is_mx6q() || cpu_is_mx6dl()) &&
			((ldb->mode == LDB_SEP0) || (ldb->mode == LDB_SEP1)))
			ldb_clk[6] += lvds_channel;
		else
			ldb_clk[6] += setting->disp_id;
		ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev,
								ldb_clk);
		if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) {
			dev_err(&ldb->pdev->dev, "get ldb clk0 failed\n");
			iounmap(ldb->reg);
			return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk);
		}
		di_clk[3] += setting->dev_id;
		di_clk[7] += setting->disp_id;
		ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev,
								di_clk);
		if (IS_ERR(ldb->setting[setting_idx].di_clk)) {
			dev_err(&ldb->pdev->dev, "get di clk0 failed\n");
			iounmap(ldb->reg);
			return PTR_ERR(ldb->setting[setting_idx].di_clk);
		}

		dev_dbg(&ldb->pdev->dev, "ldb_clk to di clk: %s -> %s\n", ldb_clk, di_clk);

		/* fb notifier for clk setting */
		ldb->nb.notifier_call = ldb_fb_event,
		ret = fb_register_client(&ldb->nb);
		if (ret < 0) {
			iounmap(ldb->reg);
			return ret;
		}

		ldb->inited = true;
	} else { /* second time for separate mode */
		char di_clk[] = "ipu1_di0_clk";
		char ldb_clk[] = "ldb_di0_clk";
		int lvds_channel;

		if ((ldb->mode == LDB_SPL_DI0) ||
			(ldb->mode == LDB_SPL_DI1) ||
			(ldb->mode == LDB_DUL_DI0) ||
			(ldb->mode == LDB_DUL_DI1) ||
			(ldb->mode == LDB_SIN0) ||
			(ldb->mode == LDB_SIN1)) {
			dev_err(&ldb->pdev->dev, "for second ldb disp"
					"ldb mode should in separate mode\n");
			return -EINVAL;
		}

		setting_idx = 1;
		if (cpu_is_mx6q() || cpu_is_mx6dl()) {
			setting->dev_id = plat_data->sec_ipu_id;
			setting->disp_id = plat_data->sec_disp_id;
		} else {
			setting->dev_id = plat_data->ipu_id;
			setting->disp_id = !plat_data->disp_id;
		}
		if (setting->disp_id == ldb->setting[0].di) {
			dev_err(&ldb->pdev->dev, "Err: for second ldb disp in"
				"separate mode, DI should be different!\n");
			return -EINVAL;
		}

		/* second output is LVDS0 or LVDS1 */
		if (ldb->mode == LDB_SEP0)
			lvds_channel = 1;
		else
			lvds_channel = 0;

		reg = readl(ldb->control_reg);
		if ((lvds_channel == 0) && (setting->disp_id == 0))
			reg |= LDB_CH0_MODE_EN_TO_DI0;
		else if ((lvds_channel == 0) && (setting->disp_id == 1))
			reg |= LDB_CH0_MODE_EN_TO_DI1;
		else if ((lvds_channel == 1) && (setting->disp_id == 0))
			reg |= LDB_CH1_MODE_EN_TO_DI0;
		else
			reg |= LDB_CH1_MODE_EN_TO_DI1;
		ch_mask = lvds_channel ?  LDB_CH1_MODE_MASK :
				LDB_CH0_MODE_MASK;
		ch_val = reg & ch_mask;

		if (bits_per_pixel(setting->if_fmt) == 24) {
			if (lvds_channel == 0)
				reg |= LDB_DATA_WIDTH_CH0_24;
			else
				reg |= LDB_DATA_WIDTH_CH1_24;
		} else {
			if (lvds_channel == 0)
				reg |= LDB_DATA_WIDTH_CH0_18;
			else
				reg |= LDB_DATA_WIDTH_CH1_18;
		}
		writel(reg, ldb->control_reg);

		/* clock setting */
		if (cpu_is_mx6q() || cpu_is_mx6dl())
			ldb_clk[6] += lvds_channel;
		else
			ldb_clk[6] += setting->disp_id;
		ldb->setting[setting_idx].ldb_di_clk = clk_get(&ldb->pdev->dev,
								ldb_clk);
		if (IS_ERR(ldb->setting[setting_idx].ldb_di_clk)) {
			dev_err(&ldb->pdev->dev, "get ldb clk1 failed\n");
			return PTR_ERR(ldb->setting[setting_idx].ldb_di_clk);
		}
		di_clk[3] += setting->dev_id;
		di_clk[7] += setting->disp_id;
		ldb->setting[setting_idx].di_clk = clk_get(&ldb->pdev->dev,
								di_clk);
		if (IS_ERR(ldb->setting[setting_idx].di_clk)) {
			dev_err(&ldb->pdev->dev, "get di clk1 failed\n");
			return PTR_ERR(ldb->setting[setting_idx].di_clk);
		}

		dev_dbg(&ldb->pdev->dev, "ldb_clk to di clk: %s -> %s\n", ldb_clk, di_clk);
	}

	ldb->setting[setting_idx].ch_mask = ch_mask;
	ldb->setting[setting_idx].ch_val = ch_val;

	if (cpu_is_mx6q() || cpu_is_mx6dl())
		ldb_ipu_ldb_route(setting->dev_id, setting->disp_id, ldb);

	/*
	 * ldb_di0_clk -> ipux_di0_clk
	 * ldb_di1_clk -> ipux_di1_clk
	 */
	clk_set_parent(ldb->setting[setting_idx].di_clk,
			ldb->setting[setting_idx].ldb_di_clk);

	/* must use spec video mode defined by driver */
	ret = fb_find_mode(&setting->fbi->var, setting->fbi, setting->dft_mode_str,
				ldb_modedb, ldb_modedb_sz, NULL, setting->default_bpp);
	if (ret != 1)
		fb_videomode_to_var(&setting->fbi->var, &ldb_modedb[0]);

	INIT_LIST_HEAD(&setting->fbi->modelist);
	for (i = 0; i < ldb_modedb_sz; i++) {
		struct fb_videomode m;
		fb_var_to_videomode(&m, &setting->fbi->var);
		if (fb_mode_is_equal(&m, &ldb_modedb[i])) {
			fb_add_videomode(&ldb_modedb[i],
					&setting->fbi->modelist);
			break;
		}
	}

	/* save current ldb setting for fb notifier */
	ldb->setting[setting_idx].active = true;
	ldb->setting[setting_idx].ipu = setting->dev_id;
	ldb->setting[setting_idx].di = setting->disp_id;

	return ret;
}
Esempio n. 5
0
/*!
 * This function is called by the driver framework to initialize the LDB
 * device.
 *
 * @param	dev	The device structure for the LDB passed in by the
 *			driver framework.
 *
 * @return      Returns 0 on success or negative error code on error
 */
static int ldb_probe(struct platform_device *pdev)
{
	int ret = 0, i, ipu_di, ipu_di_pix_fmt[2];
	bool primary = false, find_1080p = false;
	struct resource *res;
	struct ldb_platform_data *plat_data = pdev->dev.platform_data;
	mm_segment_t old_fs;
	struct clk *ldb_clk_parent;
	unsigned long ldb_clk_prate = 455000000;
	struct fb_var_screeninfo *var[2];
	uint32_t reg;
	struct device *temp;
	int mxc_ldb_major;
	const struct fb_videomode *mode;
	struct class *mxc_ldb_class;

	if (g_enable_ldb == false)
		return -ENODEV;

	spin_lock_init(&ldb_lock);

	g_ldb_dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (IS_ERR(res))
		return -ENODEV;

	memset(&ldb, 0, sizeof(struct ldb_data));
	enabled[0] = enabled[1] = false;
	var[0] = var[1] = NULL;
	if (g_boot_cmd) {
		ldb.chan_mode_opt = g_chan_mode_opt;
		ldb.chan_bit_map[0] = g_chan_bit_map[0];
		ldb.chan_bit_map[1] = g_chan_bit_map[1];
	}

	ldb.base_addr = res->start;
	ldb_reg = ioremap(ldb.base_addr, res->end - res->start + 1);
	ldb.control_reg = ldb_reg + 2;

	INIT_LIST_HEAD(&ldb.modelist);
	for (i = 0; i < mxcfb_ldb_modedb_sz; i++)
		fb_add_videomode(&mxcfb_ldb_modedb[i], &ldb.modelist);

	for (i = 0; i < num_registered_fb; i++) {
		if ((registered_fb[i]->var.sync & FB_SYNC_EXT) &&
		    (registered_fb[i]->var.vmode == FB_VMODE_NONINTERLACED)) {
			ldb.fbi[i] = registered_fb[i];

			mode = fb_match_mode(&ldb.fbi[i]->var, &ldb.modelist);
			if (mode) {
				dev_dbg(g_ldb_dev, "fb mode found\n");
				fb_videomode_to_var(&ldb.fbi[i]->var, mode);
			} else {
				dev_warn(g_ldb_dev,
						"can't find video mode\n");
				goto err0;
			}
			/*
			 * Default ldb mode:
			 * 1080p: DI0 split, SPWG or DI1 split, SPWG
			 * others: single, SPWG
			 */
			if (g_boot_cmd == false) {
				if (fb_mode_is_equal(mode, &mxcfb_ldb_modedb[0])) {
					if (strcmp(ldb.fbi[i]->fix.id,
					    "DISP3 BG") == 0) {
						ldb.chan_mode_opt = LDB_SPL_DI0;
						dev_warn(g_ldb_dev,
							"default di0 split mode\n");
					} else if (strcmp(ldb.fbi[i]->fix.id,
						   "DISP3 BG - DI1") == 0) {
						ldb.chan_mode_opt = LDB_SPL_DI1;
						dev_warn(g_ldb_dev,
							"default di1 split mode\n");
					}
					ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG;
					ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG;
					find_1080p = true;
				} else if (!find_1080p) {
					if (strcmp(ldb.fbi[i]->fix.id,
					    "DISP3 BG") == 0) {
						ldb.chan_mode_opt = LDB_SIN_DI0;
						ldb.chan_bit_map[0] = LDB_BIT_MAP_SPWG;
						dev_warn(g_ldb_dev,
							 "default di0 single mode\n");
					} else if (strcmp(ldb.fbi[i]->fix.id,
						   "DISP3 BG - DI1") == 0) {
						ldb.chan_mode_opt = LDB_SIN_DI1;
						ldb.chan_bit_map[1] = LDB_BIT_MAP_SPWG;
						dev_warn(g_ldb_dev,
							 "default di1 single mode\n");
					}
				}
			}

			acquire_console_sem();
			fb_blank(ldb.fbi[i], FB_BLANK_POWERDOWN);
			release_console_sem();

			if (i == 0)
				primary = true;

			if (ldb.fbi[1] != NULL)
				break;
		}
	}

	/*
	 * We cannot support two LVDS panel with different pixel clock rates
	 * except that one's pixel clock rate is two times of the others'.
	 */
	if (ldb.fbi[1] && ldb.fbi[0] != NULL) {
		if (ldb.fbi[0]->var.pixclock != ldb.fbi[1]->var.pixclock &&
		    ldb.fbi[0]->var.pixclock != 2 * ldb.fbi[1]->var.pixclock &&
		    ldb.fbi[1]->var.pixclock != 2 * ldb.fbi[0]->var.pixclock)
			return -EINVAL;
	}

	ldb.bgref_rmode = plat_data->ext_ref;
	ldb.lvds_bg_reg = regulator_get(&pdev->dev, plat_data->lvds_bg_reg);
	if (!IS_ERR(ldb.lvds_bg_reg)) {
		regulator_set_voltage(ldb.lvds_bg_reg, 2500000, 2500000);
		regulator_enable(ldb.lvds_bg_reg);
	}

	for (i = 0; i < 2; i++) {
		if (ldb.fbi[i] != NULL) {
			if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG") == 0)
				ipu_di = 0;
			else if (strcmp(ldb.fbi[i]->fix.id, "DISP3 BG - DI1")
				 == 0)
				ipu_di = 1;
			else {
				dev_err(g_ldb_dev, "Wrong framebuffer\n");
				goto err0;
			}

			var[ipu_di] = &ldb.fbi[i]->var;
			if (ldb.fbi[i]->fbops->fb_ioctl) {
				old_fs = get_fs();
				set_fs(KERNEL_DS);
				ldb.fbi[i]->fbops->fb_ioctl(ldb.fbi[i],
						MXCFB_GET_DIFMT,
						(unsigned long)&(ipu_di_pix_fmt[ipu_di]));
				set_fs(old_fs);
			} else {
				dev_err(g_ldb_dev, "Can't get framebuffer "
						   "information\n");
				goto err0;
			}

			if (!valid_mode(ipu_di_pix_fmt[ipu_di])) {
				dev_err(g_ldb_dev, "Unsupport pixel format "
						   "for ldb input\n");
				goto err0;
			}

			reg = __raw_readl(ldb.control_reg);
			if (var[ipu_di]->sync & FB_SYNC_VERT_HIGH_ACT) {
				if (ipu_di == 0)
					__raw_writel((reg &
						~LDB_DI0_VS_POL_MASK) |
						LDB_DI0_VS_POL_ACT_HIGH,
						ldb.control_reg);
				else
					__raw_writel((reg &
						~LDB_DI1_VS_POL_MASK) |
						LDB_DI1_VS_POL_ACT_HIGH,
						ldb.control_reg);
			} else {
				if (ipu_di == 0)
					__raw_writel((reg &
						~LDB_DI0_VS_POL_MASK) |
						LDB_DI0_VS_POL_ACT_LOW,
						ldb.control_reg);
				else
					__raw_writel((reg &
						~LDB_DI1_VS_POL_MASK) |
						LDB_DI1_VS_POL_ACT_LOW,
						ldb.control_reg);
			}

			/* TODO:Set the correct pll4 rate for all situations */
			if (ipu_di == 1) {
				ldb.ldb_di_clk[1] =
					clk_get(&pdev->dev, "ldb_di1_clk");
				ldb_clk_parent =
					clk_get_parent(ldb.ldb_di_clk[1]);
				clk_set_rate(ldb_clk_parent, ldb_clk_prate);
				clk_put(ldb.ldb_di_clk[1]);
			} else {
				ldb.ldb_di_clk[0] =
					clk_get(&pdev->dev, "ldb_di0_clk");
				ldb_clk_parent =
					clk_get_parent(ldb.ldb_di_clk[0]);
				clk_set_rate(ldb_clk_parent, ldb_clk_prate);
				clk_put(ldb.ldb_di_clk[0]);
			}
		}
	}

	reg = __raw_readl(ldb.control_reg);
	if (ldb.bgref_rmode == LDB_EXT_REF)
		__raw_writel((reg & ~LDB_BGREF_RMODE_MASK) |
			      LDB_BGREF_RMODE_EXT, ldb.control_reg);
	else
		__raw_writel((reg & ~LDB_BGREF_RMODE_MASK) |
			      LDB_BGREF_RMODE_INT, ldb.control_reg);

	switch (ldb.chan_mode_opt) {
	case LDB_SIN_DI0:
		if (var[0] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffer on DI0\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
				      LDB_DATA_WIDTH_CH0_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
				      LDB_DATA_WIDTH_CH0_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_JEIDA,
				      ldb.control_reg);

		ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk");
		clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7);
		clk_enable(ldb.ldb_di_clk[0]);
		clk_put(ldb.ldb_di_clk[0]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~LDB_CH0_MODE_MASK) |
			      LDB_CH0_MODE_EN_TO_DI0, ldb.control_reg);
		ldb.ch_working[0] = true;
		break;
	case LDB_SIN_DI1:
		if (var[1] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffer on DI1\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
				      LDB_DATA_WIDTH_CH1_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
				      LDB_DATA_WIDTH_CH1_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_JEIDA,
				      ldb.control_reg);

		ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk");
		clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7);
		clk_enable(ldb.ldb_di_clk[1]);
		clk_put(ldb.ldb_di_clk[1]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~LDB_CH1_MODE_MASK) |
			      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
		ldb.ch_working[1] = true;
		break;
	case LDB_SEP:
		if (var[0] == NULL || var[1] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffers on DI0/1\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
				      LDB_DATA_WIDTH_CH0_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
				      LDB_DATA_WIDTH_CH0_18,
				      ldb.control_reg);
		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
				      LDB_DATA_WIDTH_CH1_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18)
			__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
				      LDB_DATA_WIDTH_CH1_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_JEIDA,
				      ldb.control_reg);
		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_JEIDA,
				      ldb.control_reg);

		ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk");
		clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7);
		clk_enable(ldb.ldb_di_clk[0]);
		clk_put(ldb.ldb_di_clk[0]);
		ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk");
		clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7);
		clk_enable(ldb.ldb_di_clk[1]);
		clk_put(ldb.ldb_di_clk[1]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
				      LDB_CH1_MODE_MASK)) |
			      LDB_CH0_MODE_EN_TO_DI0 |
			      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
		ldb.ch_working[0] = true;
		ldb.ch_working[1] = true;
		break;
	case LDB_DUL_DI0:
	case LDB_SPL_DI0:
		if (var[0] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffer on DI0\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[0]) == 24)
			__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
					      LDB_DATA_WIDTH_CH1_MASK)) |
				      LDB_DATA_WIDTH_CH0_24 |
				      LDB_DATA_WIDTH_CH1_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[0]) == 18)
			__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
					      LDB_DATA_WIDTH_CH1_MASK)) |
				      LDB_DATA_WIDTH_CH0_18 |
				      LDB_DATA_WIDTH_CH1_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_JEIDA,
				      ldb.control_reg);
		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_JEIDA,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_mode_opt == LDB_SPL_DI0)
			__raw_writel(reg | LDB_SPLIT_MODE_EN,
				      ldb.control_reg);

		ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk");
		ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk");
		if (ldb.chan_mode_opt == LDB_DUL_DI0) {
			clk_set_rate(ldb.ldb_di_clk[0], ldb_clk_prate/7);
		} else {
			clk_set_rate(ldb.ldb_di_clk[0], 2*ldb_clk_prate/7);
			clk_set_rate(ldb.ldb_di_clk[1], 2*ldb_clk_prate/7);
		}
		clk_enable(ldb.ldb_di_clk[0]);
		clk_enable(ldb.ldb_di_clk[1]);
		clk_put(ldb.ldb_di_clk[0]);
		clk_put(ldb.ldb_di_clk[1]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
				      LDB_CH1_MODE_MASK)) |
			      LDB_CH0_MODE_EN_TO_DI0 |
			      LDB_CH1_MODE_EN_TO_DI0, ldb.control_reg);
		ldb.ch_working[0] = true;
		ldb.ch_working[1] = true;
		break;
	case LDB_DUL_DI1:
	case LDB_SPL_DI1:
		if (var[1] == NULL) {
			dev_err(g_ldb_dev, "Can't find framebuffer on DI1\n");
			break;
		}

		reg = __raw_readl(ldb.control_reg);
		if (bits_per_pixel(ipu_di_pix_fmt[1]) == 24)
			__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
					      LDB_DATA_WIDTH_CH1_MASK)) |
				      LDB_DATA_WIDTH_CH0_24 |
				      LDB_DATA_WIDTH_CH1_24,
				      ldb.control_reg);
		else if (bits_per_pixel(ipu_di_pix_fmt[1]) == 18)
			__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
					      LDB_DATA_WIDTH_CH1_MASK)) |
				      LDB_DATA_WIDTH_CH0_18 |
				      LDB_DATA_WIDTH_CH1_18,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
				      LDB_BIT_MAP_CH0_JEIDA,
				      ldb.control_reg);
		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_SPWG,
				      ldb.control_reg);
		else
			__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
				      LDB_BIT_MAP_CH1_JEIDA,
				      ldb.control_reg);

		reg = __raw_readl(ldb.control_reg);
		if (ldb.chan_mode_opt == LDB_SPL_DI1)
			__raw_writel(reg | LDB_SPLIT_MODE_EN,
				      ldb.control_reg);

		ldb.ldb_di_clk[0] = clk_get(NULL, "ldb_di0_clk");
		ldb.ldb_di_clk[1] = clk_get(NULL, "ldb_di1_clk");
		if (ldb.chan_mode_opt == LDB_DUL_DI1) {
			clk_set_rate(ldb.ldb_di_clk[1], ldb_clk_prate/7);
		} else {
			clk_set_rate(ldb.ldb_di_clk[0], 2*ldb_clk_prate/7);
			clk_set_rate(ldb.ldb_di_clk[1], 2*ldb_clk_prate/7);
		}
		clk_enable(ldb.ldb_di_clk[0]);
		clk_enable(ldb.ldb_di_clk[1]);
		clk_put(ldb.ldb_di_clk[0]);
		clk_put(ldb.ldb_di_clk[1]);

		reg = __raw_readl(ldb.control_reg);
		__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
				      LDB_CH1_MODE_MASK)) |
			      LDB_CH0_MODE_EN_TO_DI1 |
			      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
		ldb.ch_working[0] = true;
		ldb.ch_working[1] = true;
		break;
	default:
		break;
	}

	mxc_ldb_major = register_chrdev(0, "mxc_ldb", &mxc_ldb_fops);
	if (mxc_ldb_major < 0) {
		dev_err(g_ldb_dev, "Unable to register MXC LDB as a char "
				   "device\n");
		ret = mxc_ldb_major;
		goto err0;
	}

	mxc_ldb_class = class_create(THIS_MODULE, "mxc_ldb");
	if (IS_ERR(mxc_ldb_class)) {
		dev_err(g_ldb_dev, "Unable to create class for MXC LDB\n");
		ret = PTR_ERR(mxc_ldb_class);
		goto err1;
	}

	temp = device_create(mxc_ldb_class, NULL, MKDEV(mxc_ldb_major, 0),
			NULL, "mxc_ldb");
	if (IS_ERR(temp)) {
		dev_err(g_ldb_dev, "Unable to create class device for "
				   "MXC LDB\n");
		ret = PTR_ERR(temp);
		goto err2;
	}

	ret = fb_register_client(&nb);
	if (ret < 0)
		goto err2;

	if (primary && ldb.fbi[0] != NULL) {
		acquire_console_sem();
		fb_blank(ldb.fbi[0], FB_BLANK_UNBLANK);
		release_console_sem();
		fb_show_logo(ldb.fbi[0], 0);
	}

	return ret;
err2:
	class_destroy(mxc_ldb_class);
err1:
	unregister_chrdev(mxc_ldb_major, "mxc_ldb");
err0:
	iounmap(ldb_reg);
	return ret;
}
Esempio n. 6
0
static DBusHandlerResult msg_handler(DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data)
{
  DBusHandlerResult   status    = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  DBusMessage        *reply     = 0;
  const char         *interface = dbus_message_get_interface(msg);
  const char         *member    = dbus_message_get_member(msg);
  const char         *object    = dbus_message_get_path(msg);
  int                 type      = dbus_message_get_type(msg);
  const char *xml = 	"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
    		    	"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
    		    	"<node name=\"/com/meego/usb_moded\">\n"
    		    	"  <interface name=\"com.meego.usb_moded\">\n"
    		    	"    <method name=\"mode_request\">\n"
    	            	"      <arg name=\"mode\" type=\"s\" direction=\"out\"/>\n"
    	            	"    </method>\n"
    	            	"    <method name=\"set_mode\">\n"
    		    	"      <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"
    		    	"    </method>\n"
    		    	"    <signal name=\"sig_usb_state_ind\">\n"
    			"      <arg name=\"mode\" type=\"s\"/>\n"
    			"    </signal>\n"
    			"  </interface>\n"
    			"	</node>\n";

  (void)user_data;

  if(!interface || !member || !object) goto EXIT;

  if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && !strcmp(interface, USB_MODE_INTERFACE) && !strcmp(object, USB_MODE_OBJECT))
  {
  	status = DBUS_HANDLER_RESULT_HANDLED;
  	
    	if(!strcmp(member, USB_MODE_STATE_REQUEST))
    	{
		const char *mode = get_usb_mode();

      		if((reply = dbus_message_new_method_return(msg)))
        		dbus_message_append_args (reply, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID);
    	}
    	else if(!strcmp(member, USB_MODE_STATE_SET))
    	{
      		char *use = 0;
      		DBusError   err = DBUS_ERROR_INIT;

      		if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID))
        		reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
		else
		{
				/* check if usb is connected, since it makes no sense to change mode if it isn't */
				if(!get_usb_connection_state())
				{
					log_warning("USB not connected, not changing mode!\n");
					goto error_reply;
				}
				/* check if the mode exists */
				if(valid_mode(use))
					goto error_reply;
				/* do not change mode if the mode requested is the one already set */
				if(strcmp(use, get_usb_mode()) != 0)
					set_usb_mode(use);
      				if((reply = dbus_message_new_method_return(msg)))
			        	dbus_message_append_args (reply, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID);
				else
error_reply:
       					reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
		}
		dbus_error_free(&err);
        }
	else if(!strcmp(member, USB_MODE_CONFIG_SET))
	{
	  	char *config = 0;
      		DBusError   err = DBUS_ERROR_INIT;

      		if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID))
        		reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
		else
		{
			/* error checking is done when setting configuration */
			if(!set_mode_setting(config))
			{
 				if((reply = dbus_message_new_method_return(msg)))
			       	dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID);
			}
			else
       				reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config);
		}
		dbus_error_free(&err);	
	}
	else if(!strcmp(member, USB_MODE_NETWORK_SET))
	{
	  	char *config = 0, *setting = 0;
      		DBusError   err = DBUS_ERROR_INIT;

      		if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID))
        		reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
		else
		{
			/* error checking is done when setting configuration */
			if(!set_network_setting(config, setting))
			{
 				if((reply = dbus_message_new_method_return(msg)))
			       	dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID);
				usb_network_update();
			}
			else
       				reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config);
		}
		dbus_error_free(&err);	
	}
	else if(!strcmp(member, USB_MODE_NETWORK_GET))
	{
		char *config = 0;
		const char *setting = 0;
		DBusError   err = DBUS_ERROR_INIT;

		if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID))
		{
			reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
		}
		else
		{
			setting = get_network_setting(config);
			if(setting)
			{
				if((reply = dbus_message_new_method_return(msg)))
				dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_STRING, &setting, DBUS_TYPE_INVALID);
				free((void *)setting);
			}
			else
				reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, config);
		}
	}
	else if(!strcmp(member, USB_MODE_CONFIG_GET))
	{
		const char *config = get_mode_setting();
		
      		if((reply = dbus_message_new_method_return(msg)))
        		dbus_message_append_args (reply, DBUS_TYPE_STRING, &config, DBUS_TYPE_INVALID);
		free((void *)config);
	}
	else if(!strcmp(member, USB_MODE_LIST))
	{
		 gchar *mode_list = get_mode_list();

                if((reply = dbus_message_new_method_return(msg)))
                        dbus_message_append_args (reply, DBUS_TYPE_STRING, (const char *) &mode_list, DBUS_TYPE_INVALID);
		g_free(mode_list);
	}
	else if(!strcmp(member, USB_MODE_RESCUE_OFF))
	{
		rescue_mode = FALSE;
		log_debug("Rescue mode off\n ");
		reply = dbus_message_new_method_return(msg);
	}
  	else
    	{ 
        	/*unknown methods are handled here */
      		reply = dbus_message_new_error(msg, DBUS_ERROR_UNKNOWN_METHOD, member);
    	}

    	if( !reply )
    	{
      		reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, member);
    	}
  }
  else if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && !strcmp(interface, "org.freedesktop.DBus.Introspectable") &&
           !strcmp(object, USB_MODE_OBJECT) && !strcmp(member, "Introspect"))
  {
  	status = DBUS_HANDLER_RESULT_HANDLED;

      	if((reply = dbus_message_new_method_return(msg)))
               dbus_message_append_args (reply, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID);
  }


EXIT:

  if(reply)
  {
  	if( !dbus_message_get_no_reply(msg) )
    	{	
      		if( !dbus_connection_send(connection, reply, 0) )
        		log_debug("Failed sending reply. Out Of Memory!\n");
      	}
    	dbus_message_unref(reply);
  }

  return status;
}
Esempio n. 7
0
int ldb_fb_event(struct notifier_block *nb, unsigned long val, void *v)
{
	struct fb_event *event = v;
	struct fb_info *fbi = event->info;
	mm_segment_t old_fs;
	int ipu_di = 0;

	/* Get rid of impact from FG fb */
	if (strcmp(fbi->fix.id, "DISP3 FG") == 0)
		return 0;

	if (fbi->fbops->fb_ioctl) {
		old_fs = get_fs();
		set_fs(KERNEL_DS);
		fbi->fbops->fb_ioctl(fbi,
				MXCFB_GET_FB_IPU_DI,
				(unsigned long)&ipu_di);
		set_fs(old_fs);
	} else
		return 0;

	if ((ipu_di == 0 && !g_di0_used) ||
	    (ipu_di == 1 && !g_di1_used) ||
	    ipu_di > 1)
		return 0;

	fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var,
			&fbi->modelist);

	if (!fbi->mode) {
		dev_warn(g_ldb_dev, "can not find mode for xres=%d, yres=%d\n",
				fbi->var.xres, fbi->var.yres);
		return 0;
	}

	switch (val) {
	case FB_EVENT_MODE_CHANGE: {
		int ipu_di_pix_fmt;
		uint32_t reg;

		if ((ldb.fbi[0] != NULL && ldb.chan_mode_opt != LDB_SEP) ||
		    ldb.fbi[1] != NULL)
			return 0;

		/*
		 * We cannot support two LVDS panels with different
		 * pixel clock rates except that one's pixel clock rate
		 * is two times of the others'.
		 */
		if (ldb.fbi[0]) {
			if (ldb.fbi[0]->var.pixclock == fbi->var.pixclock ||
			    ldb.fbi[0]->var.pixclock ==
						2 * fbi->var.pixclock ||
			    fbi->var.pixclock == 2 * ldb.fbi[0]->var.pixclock)
				ldb.fbi[1] = fbi;
			else
				return 0;
		} else
			ldb.fbi[0] = fbi;

		old_fs = get_fs();
		set_fs(KERNEL_DS);
		fbi->fbops->fb_ioctl(fbi, MXCFB_GET_DIFMT,
				(unsigned long)&ipu_di_pix_fmt);
		set_fs(old_fs);

		if (!valid_mode(ipu_di_pix_fmt)) {
			dev_err(g_ldb_dev, "Unsupport pixel format "
					   "for ldb input\n");
			return 0;
		}

		reg = __raw_readl(ldb.control_reg);
		if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) {
			if (ipu_di == 0)
				__raw_writel((reg &
					~LDB_DI0_VS_POL_MASK) |
					LDB_DI0_VS_POL_ACT_HIGH,
					ldb.control_reg);
			else
				__raw_writel((reg &
					~LDB_DI1_VS_POL_MASK) |
					LDB_DI1_VS_POL_ACT_HIGH,
					ldb.control_reg);
		} else {
			if (ipu_di == 0)
				__raw_writel((reg &
					~LDB_DI0_VS_POL_MASK) |
					LDB_DI0_VS_POL_ACT_LOW,
					ldb.control_reg);
			else
				__raw_writel((reg &
					~LDB_DI1_VS_POL_MASK) |
					LDB_DI1_VS_POL_ACT_LOW,
					ldb.control_reg);
		}

		switch (ldb.chan_mode_opt) {
		case LDB_SIN_DI0:
			reg = __raw_readl(ldb.control_reg);
			if (bits_per_pixel(ipu_di_pix_fmt) == 24)
				__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
					      LDB_DATA_WIDTH_CH0_24,
					      ldb.control_reg);
			else if (bits_per_pixel(ipu_di_pix_fmt) == 18)
				__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
					      LDB_DATA_WIDTH_CH0_18,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
				__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
					      LDB_BIT_MAP_CH0_SPWG,
					      ldb.control_reg);
			else
				__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
					      LDB_BIT_MAP_CH0_JEIDA,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			__raw_writel((reg & ~LDB_CH0_MODE_MASK) |
				      LDB_CH0_MODE_EN_TO_DI0, ldb.control_reg);
			if (ldb.blank[0] == FB_BLANK_UNBLANK)
				ldb.ch_working[0] = true;
			break;
		case LDB_SIN_DI1:
			reg = __raw_readl(ldb.control_reg);
			if (bits_per_pixel(ipu_di_pix_fmt) == 24)
				__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
					      LDB_DATA_WIDTH_CH1_24,
					      ldb.control_reg);
			else if (bits_per_pixel(ipu_di_pix_fmt) == 18)
				__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
					      LDB_DATA_WIDTH_CH1_18,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
				__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
					      LDB_BIT_MAP_CH1_SPWG,
					      ldb.control_reg);
			else
				__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
					      LDB_BIT_MAP_CH1_JEIDA,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			__raw_writel((reg & ~LDB_CH1_MODE_MASK) |
				      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
			if (ldb.blank[1] == FB_BLANK_UNBLANK)
				ldb.ch_working[1] = true;
			break;
		case LDB_SEP:
			reg = __raw_readl(ldb.control_reg);
			if (ipu_di == 0) {
				if (bits_per_pixel(ipu_di_pix_fmt) == 24)
					__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
						      LDB_DATA_WIDTH_CH0_24,
						      ldb.control_reg);
				else if (bits_per_pixel(ipu_di_pix_fmt) == 18)
					__raw_writel((reg & ~LDB_DATA_WIDTH_CH0_MASK) |
						      LDB_DATA_WIDTH_CH0_18,
						      ldb.control_reg);
			} else {
				if (bits_per_pixel(ipu_di_pix_fmt) == 24)
					__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
						      LDB_DATA_WIDTH_CH1_24,
						      ldb.control_reg);
				else if (bits_per_pixel(ipu_di_pix_fmt) == 18)
					__raw_writel((reg & ~LDB_DATA_WIDTH_CH1_MASK) |
						      LDB_DATA_WIDTH_CH1_18,
						      ldb.control_reg);
			}

			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
				__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
					      LDB_BIT_MAP_CH0_SPWG,
					      ldb.control_reg);
			else
				__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
					      LDB_BIT_MAP_CH0_JEIDA,
					      ldb.control_reg);
			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
				__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
					      LDB_BIT_MAP_CH1_SPWG,
					      ldb.control_reg);
			else
				__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
					      LDB_BIT_MAP_CH1_JEIDA,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
					      LDB_CH1_MODE_MASK)) |
				      LDB_CH0_MODE_EN_TO_DI0 |
				      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
			if (ldb.blank[0] == FB_BLANK_UNBLANK)
				ldb.ch_working[0] = true;
			if (ldb.blank[1] == FB_BLANK_UNBLANK)
				ldb.ch_working[1] = true;
			break;
		case LDB_DUL_DI0:
		case LDB_SPL_DI0:
			reg = __raw_readl(ldb.control_reg);
			if (bits_per_pixel(ipu_di_pix_fmt) == 24)
				__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
						      LDB_DATA_WIDTH_CH1_MASK)) |
					      LDB_DATA_WIDTH_CH0_24 |
					      LDB_DATA_WIDTH_CH1_24,
					      ldb.control_reg);
			else if (bits_per_pixel(ipu_di_pix_fmt) == 18)
				__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
						      LDB_DATA_WIDTH_CH1_MASK)) |
					      LDB_DATA_WIDTH_CH0_18 |
					      LDB_DATA_WIDTH_CH1_18,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
				__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
					      LDB_BIT_MAP_CH0_SPWG,
					      ldb.control_reg);
			else
				__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
					      LDB_BIT_MAP_CH0_JEIDA,
					      ldb.control_reg);
			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
				__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
					      LDB_BIT_MAP_CH1_SPWG,
					      ldb.control_reg);
			else
				__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
					      LDB_BIT_MAP_CH1_JEIDA,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_mode_opt == LDB_SPL_DI0)
				__raw_writel(reg | LDB_SPLIT_MODE_EN,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
					      LDB_CH1_MODE_MASK)) |
				      LDB_CH0_MODE_EN_TO_DI0 |
				      LDB_CH1_MODE_EN_TO_DI0, ldb.control_reg);
			if (ldb.blank[0] == FB_BLANK_UNBLANK) {
				ldb.ch_working[0] = true;
				ldb.ch_working[1] = true;
			}
			break;
		case LDB_DUL_DI1:
		case LDB_SPL_DI1:
			reg = __raw_readl(ldb.control_reg);
			if (bits_per_pixel(ipu_di_pix_fmt) == 24)
				__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
						      LDB_DATA_WIDTH_CH1_MASK)) |
					      LDB_DATA_WIDTH_CH0_24 |
					      LDB_DATA_WIDTH_CH1_24,
					      ldb.control_reg);
			else if (bits_per_pixel(ipu_di_pix_fmt) == 18)
				__raw_writel((reg & ~(LDB_DATA_WIDTH_CH0_MASK |
						      LDB_DATA_WIDTH_CH1_MASK)) |
					      LDB_DATA_WIDTH_CH0_18 |
					      LDB_DATA_WIDTH_CH1_18,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_bit_map[0] == LDB_BIT_MAP_SPWG)
				__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
					      LDB_BIT_MAP_CH0_SPWG,
					      ldb.control_reg);
			else
				__raw_writel((reg & ~LDB_BIT_MAP_CH0_MASK) |
					      LDB_BIT_MAP_CH0_JEIDA,
					      ldb.control_reg);
			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_bit_map[1] == LDB_BIT_MAP_SPWG)
				__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
					      LDB_BIT_MAP_CH1_SPWG,
					      ldb.control_reg);
			else
				__raw_writel((reg & ~LDB_BIT_MAP_CH1_MASK) |
					      LDB_BIT_MAP_CH1_JEIDA,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			if (ldb.chan_mode_opt == LDB_SPL_DI1)
				__raw_writel(reg | LDB_SPLIT_MODE_EN,
					      ldb.control_reg);

			reg = __raw_readl(ldb.control_reg);
			__raw_writel((reg & ~(LDB_CH0_MODE_MASK |
					      LDB_CH1_MODE_MASK)) |
				      LDB_CH0_MODE_EN_TO_DI1 |
				      LDB_CH1_MODE_EN_TO_DI1, ldb.control_reg);
			if (ldb.blank[1] == FB_BLANK_UNBLANK) {
				ldb.ch_working[0] = true;
				ldb.ch_working[1] = true;
			}
			break;
		default:
			break;
		}
		break;
	}
	case FB_EVENT_BLANK: {
		if (ldb.fbi[0] != fbi && ldb.fbi[1] != fbi)
			return 0;

		if (*((int *)event->data) == ldb.blank[ipu_di])
			return 0;

		if (*((int *)event->data) == FB_BLANK_UNBLANK)
			ldb_enable(ipu_di);
		else
			ldb_disable(ipu_di);

		ldb.blank[ipu_di] = *((int *)event->data);
		break;
	}
	default:
		break;
	}
	return 0;
}