예제 #1
0
int siw_touch_boot_mode_check(struct device *dev)
{
	struct siw_ts *ts = to_touch_core(dev);
	int ret = NORMAL_BOOT;

#if defined(CONFIG_SIW_GET_FACTORY_MODE)
	ret = sys_get_factory_boot();
#elif defined(CONFIG_TOUCHSCREEN_SIW_LG4895_F650) ||	\
	defined(CONFIG_TOUCHSCREEN_SIW_LG4946_F700)
	ret = lge_get_factory_boot();
#endif

	if (ret != NORMAL_BOOT) {
		switch (atomic_read(&ts->state.mfts)) {
			case MFTS_NONE :
				ret = MINIOS_AAT;
				break;
			case MFTS_FOLDER :
				ret = MINIOS_MFTS_FOLDER;
				break;
			case MFTS_FLAT :
				ret = MINIOS_MFTS_FLAT;
				break;
			case MFTS_CURVED :
				ret = MINIOS_MFTS_CURVED;
				break;
			default :
				ret = MINIOS_AAT;
				break;
		}
	}

	return ret;
}
예제 #2
0
static int siw_drm_register_client(struct device *dev)
{
	struct siw_ts *ts = to_touch_core(dev);

	t_dev_info(dev, "drm_register_client - sys_fb_notif\n");

	ts->fb_ret_revert_resume = DRM_RET_NOOP;
	ts->fb_ret_revert_suspend = DRM_RET_NOOP;
	ts->fb_ret_early_resume = DRM_RET_NOOP;
	ts->fb_ret_early_suspend = DRM_RET_NOOP;
	ts->fb_ret_resume = DRM_RET_NOOP;
	ts->fb_ret_suspend = DRM_RET_NOOP;

#if defined(__SIW_PANEL_CLASS_MOBILE_OLED)
	snprintf(ts->fb_msg_unblank, sizeof(ts->fb_msg_unblank), "drm_unblank");
	snprintf(ts->fb_msg_blank, sizeof(ts->fb_msg_blank), "drm_blank");

	ts->fb_ret_suspend = DRM_SUSPEND;		/* suspend later */
	ts->fb_ret_resume = DRM_RESUME;			/* resume later */
#elif defined(__SIW_CONFIG_SYSTEM_PM)
	snprintf(ts->fb_msg_unblank, sizeof(ts->fb_msg_unblank), "drm_unblank");
	snprintf(ts->fb_msg_blank, sizeof(ts->fb_msg_blank), "drm_blank");

	ts->fb_ret_revert_resume = DRM_RESUME;	/* revert to resume */
	ts->fb_ret_early_suspend = DRM_SUSPEND;	/* suspend early */
	ts->fb_ret_resume = DRM_RESUME;			/* resume later */
#else	/* */
	snprintf(ts->fb_msg_unblank, sizeof(ts->fb_msg_unblank), "DRM_UNBLANK");
	snprintf(ts->fb_msg_blank, sizeof(ts->fb_msg_blank), "DRM_BLANK");
#endif

	ts->sys_fb_notif.notifier_call = siw_drm_notifier_callback;

	return __drm_register_client(&ts->sys_fb_notif);
}
int ext_watch_check_font_download(struct device *dev)
{
	struct touch_core_data *ts = to_touch_core(dev);
	struct lg4945_data *d = to_lg4945_data(dev);
	int ret = 0;

	TOUCH_I("%s:start\n", __func__);
	if (atomic_read(&d->watch.state.is_font) != DOWN_LOADED) {
		TOUCH_I("%s : font data is not\n", __func__);
		return -ENOMEM;
	}

	if (touch_mfts_mode_check(dev))
		return -EBUSY;

	if (atomic_read(&d->watch.state.font_mem) == DOWN_LOADING) {
		TOUCH_I("%s : doing download..\n", __func__);
		return -EBUSY;
	}
	if (atomic_read(&d->watch.state.font_mem) == DOWN_LOADED) {
		TOUCH_I("%s : not need download..\n", __func__);
		return -EBUSY;
	}

	if (d->watch.ext_wdata.font_data == NULL) {
		TOUCH_E("%s : font data is not ready\n",
			__func__);
		return -ENOMEM;
	}

	queue_delayed_work(ts->wq, &d->font_download_work, 0);

	return ret;
}
예제 #4
0
static int siw_drm_unregister_client(struct device *dev)
{
	struct siw_ts *ts = to_touch_core(dev);

	t_dev_info(dev, "drm_unregister_client - sys_fb_notif\n");

	return __drm_unregister_client(&ts->sys_fb_notif);
}
int touch_mfts_mode_check(struct device *dev)
{
	struct touch_core_data *ts = to_touch_core(dev);
	int ret = 0;

	ret = atomic_read(&ts->state.mfts);

	return ret;
}
int touch_bus_write(struct device *dev, struct touch_bus_msg *msg)
{
	struct touch_core_data *ts = to_touch_core(dev);
	int ret = 0;

	if (ts->bus_type == HWIF_I2C)
		ret = touch_i2c_write(to_i2c_client(dev), msg);
	else if (ts->bus_type == HWIF_SPI)
		ret = touch_spi_write(to_spi_device(dev), msg);

	return ret;
}
int touch_bus_xfer(struct device *dev, struct touch_xfer_msg *xfer)
{
	struct touch_core_data *ts = to_touch_core(dev);
	int ret = 0;

	if (ts->bus_type == HWIF_I2C) {
		TOUCH_E("Not implemented\n");
		ret = -1;
	} else if (ts->bus_type == HWIF_SPI) {
		ret = touch_spi_xfer(to_spi_device(dev), xfer);
	}

	return ret;
}
void touch_power_vio(struct device *dev, int value)
{
	struct touch_core_data *ts = to_touch_core(dev);
	int ret = 0;

	if (gpio_is_valid(ts->vio_pin)) {
		ret = gpio_direction_output(ts->vio_pin, value);
	} else if (!IS_ERR_OR_NULL(ts->vio)) {
		if (value)
			ret = regulator_enable((struct regulator *)ts->vio);
		else
			ret = regulator_disable((struct regulator *)ts->vio);
	}

	if (ret)
		TOUCH_E("ret = %d", ret);
}
void ext_watch_font_download_func(
	struct work_struct *font_download_work)
{
	struct lg4945_data *d =
		container_of(to_delayed_work(font_download_work),
				struct lg4945_data, font_download_work);
	struct touch_core_data *ts = to_touch_core(d->dev);

	u32 wdata = 0;
	int ret = 0;

	if (d->lcd_mode != LCD_MODE_U3) {
		TOUCH_E("skip font download, lcd mode[U%d]\n", d->lcd_mode);
		ret = -EBUSY;
		goto error;
	}

	TOUCH_I("%s start\n", __func__);
	/* Font memory access enable */
	wdata = 1;
	ret = lg4945_reg_write(ts->dev, EXT_WATCH_FONT_ACC_EN,
		(u8 *)&wdata, sizeof(u32));
	if (ret)
		goto error;

	ret = lg4945_reg_write(ts->dev, EXT_WATCH_FONT_COMP_ADDR,
		(u8 *)d->watch.ext_wdata.comp_buf,
		COMP_FONTM_MAX_SIZE);

	if (ret)
		goto error;
	wdata = 0;
	ret = lg4945_reg_write(ts->dev, EXT_WATCH_FONT_ACC_EN,
		(u8 *)&wdata, sizeof(u32));
	if (ret)
		goto error;
	atomic_set(&d->watch.state.font_mem, DOWN_LOADED);
	TOUCH_I("%s done\n", __func__);
	return;
error:
	TOUCH_E("Fail [%d]\n", ret);
}
int watch_register_sysfs(struct device *dev)
{
	struct touch_core_data *ts = to_touch_core(dev);
	struct lg4945_data *d = to_lg4945_data(dev);
	int ret;

	TOUCH_TRACE();

	ret = kobject_init_and_add(&d->kobj, &watch_kobj_type,
			ts->input->dev.kobj.parent->parent,
			"%s", LGE_EXT_WATCH_NAME);

	ret = sysfs_create_group(&d->kobj, &watch_attribute_group);

	if (ret < 0) {
		TOUCH_E("failed to create sysfs\n");
		return ret;
	}

	watch_fontdata_attr_init(d);

	return ret;
}
/* -- power -- */
int touch_power_init(struct device *dev)
{
	struct touch_core_data *ts = to_touch_core(dev);

	TOUCH_TRACE();

	if (gpio_is_valid(ts->vdd_pin)) {
		gpio_request(ts->vdd_pin, "touch-vdd");
	} else {
		ts->vdd = regulator_get(dev, "vdd");
		if (IS_ERR(ts->vdd))
			TOUCH_I("regulator \"vdd\" not exist\n");
	}

	if (gpio_is_valid(ts->vio_pin)) {
		gpio_request(ts->vio_pin, "touch-vio");
	} else {
		ts->vio = regulator_get(dev, "vio");
		if (IS_ERR(ts->vio))
			TOUCH_I("regulator \"vio\" not exist\n");
	}

	return 0;
}
int touch_bus_init(struct device *dev, int buf_size)
{
	struct touch_core_data *ts = to_touch_core(dev);
	int ret = 0;

	TOUCH_TRACE();

	if (buf_size) {
		ts->tx_buf = devm_kzalloc(dev, buf_size, GFP_KERNEL);
		if (!ts->tx_buf)
			TOUCH_E("fail to allocate tx_buf\n");

		ts->rx_buf = devm_kzalloc(dev, buf_size, GFP_KERNEL);
		if (!ts->rx_buf)
			TOUCH_E("fail to allocate rx_buf\n");
	}

	ts->xfer = devm_kzalloc(dev, sizeof(struct touch_xfer_msg), GFP_KERNEL);
	if (!ts->xfer)
		TOUCH_E("fail to allocate xfer\n");

	ts->pinctrl.ctrl = devm_pinctrl_get(dev);

	if (IS_ERR_OR_NULL(ts->pinctrl.ctrl)) {
		if (PTR_ERR(ts->pinctrl.ctrl) == -EPROBE_DEFER)
			return -EPROBE_DEFER;

		TOUCH_I("Target does not use pinctrl\n");
		ts->pinctrl.ctrl = NULL;
	} else {
		ts->pinctrl.active = pinctrl_lookup_state(ts->pinctrl.ctrl,
				"touch_pin_active");

		if (IS_ERR_OR_NULL(ts->pinctrl.active))
			TOUCH_E("cannot get pinctrl.active\n");

		ts->pinctrl.suspend = pinctrl_lookup_state(ts->pinctrl.ctrl,
				"touch_pin_sleep");

		if (IS_ERR_OR_NULL(ts->pinctrl.suspend))
			TOUCH_E("cannot get pinctrl.suspend\n");

		if (!IS_ERR_OR_NULL(ts->pinctrl.active)) {
			ret = pinctrl_select_state(ts->pinctrl.ctrl,
					ts->pinctrl.active);
			if (ret)
				TOUCH_I("cannot set pinctrl.active\n");
			else
				TOUCH_I("pinctrl set active\n");
		}
	}

	if (ts->bus_type == HWIF_SPI) {
		ret = spi_setup(to_spi_device(dev));

		if (ret < 0) {
			TOUCH_E("Failed to perform SPI setup\n");
			return -ENODEV;
		}
	}

	return ret;
}
static int ext_watch_font_dump(struct device *dev, char *font_dump)
{
	struct touch_core_data *ts = to_touch_core(dev);
	u32 font_sel = 0;
	u32 font_data_offset = 0;
	u32 wdata = 0;
	u32 size = 0;
	int ret = 0;

	if (!ts->xfer) {
		TOUCH_I("%s alloc failed\n", __func__);
		return -EIO;
	}

	TOUCH_I("%s start\n", __func__);

	ts->xfer->bits_per_word = 8;
	ts->xfer->msg_count = 2;

	/* Font memory access enable */
	wdata = 1;
	ret = lg4945_reg_write(dev, EXT_WATCH_FONT_ACC_EN,
		(u8 *)&wdata, sizeof(u32));
	if (ret)
		goto error;

	size = sizeof(u32) * EXT_WATCH_FONT_NUM_SIZE;

	for (font_sel = 0; font_sel < 10; font_sel++) {
		/* Font select : '0' ~ '9' */
		font_data_offset = font_sel * size;

		ts->xfer->data[0].tx.addr = EXT_WATCH_FONT_SEL;
		ts->xfer->data[0].tx.buf = (u8 *)&font_sel;
		ts->xfer->data[0].tx.size = sizeof(u32);
		ts->xfer->data[1].rx.addr = EXT_WATCH_FONT_OFFSET_ADDR;
		ts->xfer->data[1].rx.buf = font_dump + font_data_offset;
		ts->xfer->data[1].rx.size = size;
		lg4945_xfer_msg(dev, ts->xfer);
	}

	/* Font select : ':' */
	font_data_offset = font_sel * size;
	size = sizeof(u32) * EXT_WATCH_FONT_CHAR_SIZE;

	ts->xfer->data[0].tx.addr = EXT_WATCH_FONT_SEL;
	ts->xfer->data[0].tx.buf = (u8 *)&font_sel;
	ts->xfer->data[0].tx.size = sizeof(u32);
	ts->xfer->data[1].rx.addr = EXT_WATCH_FONT_OFFSET_ADDR;
	ts->xfer->data[1].rx.buf = font_dump + font_data_offset;
	ts->xfer->data[1].rx.size = size;
	lg4945_xfer_msg(dev, ts->xfer);

	/* Font memory access disable */
	wdata = 0;
	ret = lg4945_reg_write(dev, EXT_WATCH_FONT_ACC_EN,
		(u8 *)&wdata, sizeof(u32));
	if (ret)
		goto error;

	TOUCH_I("%s done\n", __func__);
	return ret;

error:
	TOUCH_E("fail %d\n", ret);
	return -EIO;
}
static ssize_t watch_access_write(struct file *filp, struct kobject *kobj,
	struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
{
	struct lg4945_data *d = to_lg4945_data_from_kobj(kobj);
	struct touch_core_data *ts = to_touch_core(d->dev);
	ssize_t retval = -EFAULT;
	int idx = 0;
	int cur_data;
	int data_count;
	int comp_size = 4;
	int comp_real_size = 0;
	int comp_size_result = 0;
	u8 background = 0;

	if (atomic_read(&d->block_watch_cfg) == SUPPORT)
		return retval;

	if (buf == NULL) {
		TOUCH_E("%s buf is NULL\n", __func__);
		goto finish;
	}
	if (d->watch.ext_wdata.font_data == NULL) {
		TOUCH_E("%s font_data is NULL\n", __func__);
		goto finish;
	}
	if (off + count > FONT_DATA_SIZE)	{
		TOUCH_E("%s off + count[%d] is bigger than FONT_DATA_SIZE\n",
			__func__, (int)off+(int)count);
		goto finish;
	}

	d->watch.font_written_size = off + count;

	if (count == 0 && off + count >= d->watch.fontdata_size) {
		TOUCH_I("%s size error offset[%d] size[%d]\n", __func__,
				(int)off, (int)count);
	} else {
		memcpy(&d->watch.ext_wdata.font_data[off], buf, count);
		retval = count;

		if (off + count == FONT_DATA_SIZE) {
			if (off + count != FONT_DATA_SIZE) {
				TOUCH_E("%s data check.. not match\n",
					__func__);
				goto finish;
			}
			/* Font data compress */
			memset(&d->watch.ext_wdata.comp_buf[0],
			0, d->watch.font_written_comp_size);

			if (d->watch.ext_wdata.font_data[0] !=
				d->watch.ext_wdata.font_data[31])
				background = d->watch.ext_wdata.font_data[0];

			/*check font width size*/
			while (idx < 32) {
				if (!d->watch.ext_wdata.font_data[idx++])
					break;
			}
			if (idx == 1) {
				d->watch.font_width = 64;
			} else {
				d->watch.font_width = (idx - 1) << 1;
			}

			if (d->watch.font_width < 4 || d->watch.font_width > 48 ||
				(d->watch.font_width % 4) > 0) {
				TOUCH_E("font width(%d) is not multiple of 4\n",
					d->watch.font_width);
				retval = -EIO;
				goto finish;
			} else {
				TOUCH_I("font width : %dpixel\n",
					d->watch.font_width);
			}

			idx = 0;

			while (idx < d->watch.font_written_size) {
				cur_data = d->watch.ext_wdata.font_data[idx] ?
					d->watch.ext_wdata.font_data[idx]
					: background;
				idx++;
				data_count = 1;
				while (idx < d->watch.font_written_size
					&& (d->watch.ext_wdata.font_data[idx] ?
					d->watch.ext_wdata.font_data[idx]
					: background) == cur_data
					&& data_count < 0xFF) {
					idx++;
					data_count++;
				}
				if (data_count == 1) {
					cur_data |= E_COMP_1_NUM;
					d->watch.ext_wdata.comp_buf[comp_size++]
						= cur_data;
				} else if (data_count == 2) {
					cur_data |= E_COMP_2_NUM;
					d->watch.ext_wdata.comp_buf[comp_size++]
						= cur_data;
				} else if (data_count == 0xFF) {
					cur_data |= E_COMP_255_NUM;
					d->watch.ext_wdata.comp_buf[comp_size++]
						= cur_data;
				} else {
					d->watch.ext_wdata.comp_buf[comp_size++]
						= cur_data;
					d->watch.ext_wdata.comp_buf[comp_size++]
						= data_count;
				}
			}

			if (comp_size > COMP_FONTM_MAX_SIZE) {
				TOUCH_E("comp_size %d > %d\n",
					comp_size, COMP_FONTM_MAX_SIZE);
				retval = -EIO;
				goto finish;
			}

			comp_real_size = comp_size - 4;
			memcpy(&d->watch.ext_wdata.comp_buf[0], &comp_real_size, 4);

			/* write font width size to buffer */
			if ( d->fw.version[0] == 1 && d->fw.version[1] >= 30 )
				d->watch.ext_wdata.comp_buf[2] = d->watch.font_width;
			else
				TOUCH_E("not support the dynamic pixel font data[v%d.%d]\n",
				d->fw.version[0], d->fw.version[1]);

			if (comp_size % 4 == 0) {
				comp_size_result = comp_size + 4;
			} else {
				int pad_size = 4 - comp_size % 4;
				comp_size_result = comp_size + pad_size + 4;
			}
			*((u32 *)&d->watch.ext_wdata.comp_buf[(comp_size_result)
				- 4]) = COMP_FONT_TRANFER_CODE;

			TOUCH_I("font comp complete [%d][%d]\n", comp_real_size, comp_size);
			queue_delayed_work(ts->wq, &d->font_download_work, 0);
			atomic_set(&d->watch.state.is_font, DOWN_LOADED);
		} else if (off && count != PAGE_SIZE)
			TOUCH_I("%s size error offset[%d] size[%d]\n", __func__,
				(int)off, (int)count);
	}
finish:
	return retval;
}