static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *params)
{
	int i;
	struct omap_overlay_manager *mgr = NULL;
	struct device *dev = substream->pcm->card->dev;

	/* Find DSS HDMI device */
	for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
		mgr = omap_dss_get_overlay_manager(i);
		if (mgr && mgr->device
			&& mgr->device->type == OMAP_DISPLAY_TYPE_HDMI)
			break;
	}

	if (i == omap_dss_get_num_overlay_managers()) {
		dev_err(dev, "HDMI display device not found!\n");
		return -ENODEV;
	}

	/* Make sure HDMI is power-on to avoid L3 interconnect errors */
	if (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
		dev_err(dev, "HDMI display is not active!\n");
		return -EIO;
	}

	return 0;
}
Exemple #2
0
static ssize_t overlay_req_manager_store(struct omap_overlay *ovl,
		const char *buf, size_t size)
{
	int i;
	int len = size;
	struct omap_overlay_manager *mgr = NULL;
	
	if (buf[size - 1] == '\n')
		--len;
	
	if (len <= 0 || len >= MAX_MANAGER_NAME_LEN) 
		return -EINVAL;
	
	for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
		mgr = omap_dss_get_overlay_manager(i);

		if (!strncmp(buf, mgr->name, len))
			break;

		mgr = NULL;
	}

	if (mgr == NULL)
		return -EINVAL;

	memcpy(omap_overlay_info_req[ovl->id].manager, buf, len);
	omap_overlay_info_req[ovl->id].manager[len] = '\0';
	
	return size;
}
static int create_display_list(void)
{
	int i;
	struct omap_display_device *display;

	/* Query number of possible displays available first */
	omap_display_number = omap_dss_get_num_overlay_managers();
	/* For virtual display */
	omap_display_number++;

	/* Allocate custom display list */
	omap_display_list = kzalloc(
		sizeof(*display) * omap_display_number, GFP_KERNEL);

	if (!omap_display_list) {
		ERR_PRINT("Out of memory");
		return 1;
	}

	/* Populate each display info */
	for (i = 0; i < omap_display_number - 1; i++) {
		struct omap_overlay_manager *overlay_manager =
			omap_dss_get_overlay_manager(i);
		display = &omap_display_list[i];
		if (!overlay_manager->device) {
			WRN_PRINT("Display '%s' doesn't have a dss device "
				"attached to it, ignoring",
				overlay_manager->name);
			display->id = OMAP_DISPID_BADSTATE;
			continue;
		}
		if (populate_display_info(display, overlay_manager)) {
			ERR_PRINT("Error populating display %i info with "
				"manager '%s'", i,
				overlay_manager->device->name);
			display->id = OMAP_DISPID_BADSTATE;
			continue;
		}
	}

	/* Populate virtual display */
	display = &omap_display_list[omap_display_number - 1];
	if (populate_virtual_display_info(display)) {
		ERR_PRINT("Error populating virtual display info");
		display->id = OMAP_DISPID_BADSTATE;
	}

	return 0;
}
static int omap_modeset_init(struct drm_device *dev)
{
	const struct omap_drm_platform_data *pdata = dev->dev->platform_data;
	struct omap_kms_platform_data *kms_pdata = NULL;
	struct omap_drm_private *priv = dev->dev_private;
	struct omap_dss_device *dssdev = NULL;
	int i, j;
	unsigned int connected_connectors = 0;

	drm_mode_config_init(dev);

	if (pdata && pdata->kms_pdata) {
		kms_pdata = pdata->kms_pdata;

		/* if platform data is provided by the board file, use it to
		 * control which overlays, managers, and devices we own.
		 */
		for (i = 0; i < kms_pdata->mgr_cnt; i++) {
			struct omap_overlay_manager *mgr =
				omap_dss_get_overlay_manager(
						kms_pdata->mgr_ids[i]);
			create_encoder(dev, mgr);
		}

		for (i = 0; i < kms_pdata->dev_cnt; i++) {
			struct omap_dss_device *dssdev =
				omap_dss_find_device(
					(void *)kms_pdata->dev_names[i],
					match_dev_name);
			if (!dssdev) {
				dev_warn(dev->dev, "no such dssdev: %s\n",
						kms_pdata->dev_names[i]);
				continue;
			}
			create_connector(dev, dssdev);
		}

		connected_connectors = detect_connectors(dev);

		j = 0;
		for (i = 0; i < kms_pdata->ovl_cnt; i++) {
			struct omap_overlay *ovl =
				omap_dss_get_overlay(kms_pdata->ovl_ids[i]);
			create_crtc(dev, ovl, &j, connected_connectors);
		}

		for (i = 0; i < kms_pdata->pln_cnt; i++) {
			struct omap_overlay *ovl =
				omap_dss_get_overlay(kms_pdata->pln_ids[i]);
			create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
		}
	} else {
		/* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try
		 * to make educated guesses about everything else
		 */
		int max_overlays = min(omap_dss_get_num_overlays(), num_crtc);

		for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
			create_encoder(dev, omap_dss_get_overlay_manager(i));
		}

		for_each_dss_dev(dssdev) {
			create_connector(dev, dssdev);
		}

		connected_connectors = detect_connectors(dev);

		j = 0;
		for (i = 0; i < max_overlays; i++) {
			create_crtc(dev, omap_dss_get_overlay(i),
					&j, connected_connectors);
		}

		/* use any remaining overlays as drm planes */
		for (; i < omap_dss_get_num_overlays(); i++) {
			struct omap_overlay *ovl = omap_dss_get_overlay(i);
			create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
		}
	}

	/* for now keep the mapping of CRTCs and encoders static.. */
	for (i = 0; i < priv->num_encoders; i++) {
		struct drm_encoder *encoder = priv->encoders[i];
		struct omap_overlay_manager *mgr =
				omap_encoder_get_manager(encoder);

		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;

		DBG("%s: possible_crtcs=%08x", mgr->name,
					encoder->possible_crtcs);
	}

	dump_video_chains();

	dev->mode_config.min_width = 32;
	dev->mode_config.min_height = 32;

	/* note: eventually will need some cpu_is_omapXYZ() type stuff here
	 * to fill in these limits properly on different OMAP generations..
	 */
	dev->mode_config.max_width = 2048;
	dev->mode_config.max_height = 2048;

	dev->mode_config.funcs = &omap_mode_config_funcs;

	return 0;
}
static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
		size_t size)
{
	int i, r;
	struct omap_overlay_manager *mgr = NULL;
	struct omap_overlay_manager *old_mgr;
	int len = size;

	if (buf[size-1] == '\n')
		--len;

	if (len > 0) {
		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
			mgr = omap_dss_get_overlay_manager(i);

			if (sysfs_streq(buf, mgr->name))
				break;

			mgr = NULL;
		}
	}

	if (len > 0 && mgr == NULL)
		return -EINVAL;

	if (mgr)
		DSSDBG("manager %s found\n", mgr->name);

	if (mgr == ovl->manager)
		return size;

	old_mgr = ovl->manager;

	r = dispc_runtime_get();
	if (r)
		return r;

	/* detach old manager */
	if (old_mgr) {
		r = ovl->unset_manager(ovl);
		if (r) {
			DSSERR("detach failed\n");
			goto err;
		}

		r = old_mgr->apply(old_mgr);
		if (r)
			goto err;
	}

	if (mgr) {
		r = ovl->set_manager(ovl, mgr);
		if (r) {
			DSSERR("Failed to attach overlay\n");
			goto err;
		}

		r = mgr->apply(mgr);
		if (r)
			goto err;
	}

	dispc_runtime_put();

	return size;

err:
	dispc_runtime_put();
	return r;
}
Exemple #6
0
static ssize_t overlay_req_request_store(struct omap_overlay *ovl,
		const char *buf, size_t size)
{
	int ret, i, len, input;
	struct omap_overlay_manager *mgr = NULL;
	struct omap_overlay_manager *old_mgr = NULL;
	struct omap_overlay_info info;

	input = simple_strtoul(buf, NULL, 10);
	
	if(input == 1) {	//prepare
		ovl->get_overlay_info(ovl, &omap_overlay_info_req[ovl->id]);
		omap_overlay_info_req[ovl->id].status = 1;
	}
	else if((input == 2) && (1 == omap_overlay_info_req[ovl->id].status)) {	//commit
		len = strlen(omap_overlay_info_req[ovl->id].manager);
		if(len <= 0)
			goto no_need_set_manager;

		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
			mgr = omap_dss_get_overlay_manager(i);

			if (!strncmp(omap_overlay_info_req[ovl->id].manager, mgr->name, len))
				break;

			mgr = NULL;
		}

		if (mgr == NULL) 
			goto err_manager;
		
		old_mgr = ovl->manager;
		if (mgr != old_mgr) {
			/* detach old manager */
			if (old_mgr) {
				//disable overlay
				ovl->get_overlay_info(ovl, &info);
				info.enabled = 0;
				ret = ovl->set_overlay_info(ovl, &info);
				if (ret) 
					goto err_manager;
				
				ret = ovl->unset_manager(ovl);
				if (ret) {
					DSSERR("detach failed\n");
					goto err_manager;
				}

				ret = old_mgr->apply(old_mgr);
				if (ret) 
					goto err_manager;
				

				if (ret) 
					goto err_manager;
			}

			if (mgr) {
				ret = ovl->set_manager(ovl, mgr);
				if (ret) {
					DSSERR("Failed to attach overlay\n");
					goto err_manager;
				}

				ret = mgr->apply(mgr);
				if (ret) 
					goto err_manager;
			}
		}	
		omap_overlay_info_req[ovl->id].status = 2;
	}
	return size;		
	
no_need_set_manager:	
	omap_overlay_info_req[ovl->id].status = 2;
	return size;	
	
err_manager:
	omap_overlay_info_req[ovl->id].status = 3;
	return size;
}
Exemple #7
0
static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
		size_t size)
{
	int i, r;
	struct omap_overlay_manager *mgr = NULL;
	struct omap_overlay_manager *old_mgr;
	struct omap_overlay_info info;
	int len = size;

	if (buf[size-1] == '\n')
		--len;

	if (len > 0) {
		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
			mgr = omap_dss_get_overlay_manager(i);

			if (strncmp(buf, mgr->name, len) == 0)
				break;

			mgr = NULL;
		}
	}

	if (len > 0 && mgr == NULL)
		return -EINVAL;

	if (mgr)
		DSSDBG("manager %s found\n", mgr->name);

	if (mgr == ovl->manager)
		return size;

	if (mgr && sysfs_streq(mgr->name, "tv")) {
		ovl->get_overlay_info(ovl, &info);
		/* LGE_CHANGE_S [[email protected]] 2010-12-24 HDMI*/
		//OUT_WIDTH is correct
//		if (mgr->device->panel.timings.x_res < info.width ||
//			mgr->device->panel.timings.y_res < info.height) {
		if (mgr->device->panel.timings.x_res < info.out_width ||
			mgr->device->panel.timings.y_res < info.out_height) {
		/* LGE_CHANGE_E [[email protected]] 2010-12-24 HDMI*/
			printk(KERN_ERR"TV does not support downscaling"
			"Please configure overlay to supported format");
			return -EINVAL;
		}
	}

	old_mgr = ovl->manager;

	/* detach old manager */
	if (old_mgr) {
		r = ovl->unset_manager(ovl);
		if (r) {
			DSSERR("detach failed\n");
			return r;
		}

		r = old_mgr->apply(old_mgr);
		if (r)
			return r;
	}

	if (mgr) {
		r = ovl->set_manager(ovl, mgr);
		if (r) {
			DSSERR("Failed to attach overlay\n");
			return r;
		}

		r = mgr->apply(mgr);
		if (r)
			return r;
	}

	return size;
}
static void dispc_error_worker(struct work_struct *work)
{
	int i;
	u32 errors;
	unsigned long flags;
	static const unsigned fifo_underflow_bits[] = {
		DISPC_IRQ_GFX_FIFO_UNDERFLOW,
		DISPC_IRQ_VID1_FIFO_UNDERFLOW,
		DISPC_IRQ_VID2_FIFO_UNDERFLOW,
		DISPC_IRQ_VID3_FIFO_UNDERFLOW,
	};

	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
	errors = dispc_compat.error_irqs;
	dispc_compat.error_irqs = 0;
	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);

	dispc_runtime_get();

	for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
		struct omap_overlay *ovl;
		unsigned bit;

		ovl = omap_dss_get_overlay(i);
		bit = fifo_underflow_bits[i];

		if (bit & errors) {
			DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
					ovl->name);
			dispc_ovl_enable(ovl->id, false);
			dispc_mgr_go(ovl->manager->id);
			msleep(50);
		}
	}

	for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
		struct omap_overlay_manager *mgr;
		unsigned bit;

		mgr = omap_dss_get_overlay_manager(i);
		bit = dispc_mgr_get_sync_lost_irq(i);

		if (bit & errors) {
			int j;

			DSSERR("SYNC_LOST on channel %s, restarting the output "
					"with video overlays disabled\n",
					mgr->name);

			dss_mgr_disable(mgr);

			for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
				struct omap_overlay *ovl;
				ovl = omap_dss_get_overlay(j);

				if (ovl->id != OMAP_DSS_GFX &&
						ovl->manager == mgr)
					ovl->disable(ovl);
			}

			dss_mgr_enable(mgr);
		}
	}

	if (errors & DISPC_IRQ_OCP_ERR) {
		DSSERR("OCP_ERR\n");
		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
			struct omap_overlay_manager *mgr;

			mgr = omap_dss_get_overlay_manager(i);
			dss_mgr_disable(mgr);
		}
	}

	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
	dispc_compat.irq_error_mask |= errors;
	_omap_dispc_set_irqs();
	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);

	dispc_runtime_put();
}
static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
		size_t size)
{
	int i, r;
	struct omap_overlay_manager *mgr = NULL;
	struct omap_overlay_manager *old_mgr;
	struct omap_overlay_info info;
	int len = size;

	if (buf[size-1] == '\n')
		--len;

	if (len > 0) {
		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
			mgr = omap_dss_get_overlay_manager(i);
			if (!mgr) {
				WARN_ON(1);
				continue;
			}
			if (strncmp(buf, mgr->name, len) == 0)
				break;

			mgr = NULL;
		}
	}

	if (len > 0 && mgr == NULL)
		return -EINVAL;

	if (mgr)
		DSSDBG("manager %s found\n", mgr->name);

	if (mgr == ovl->manager)
		return size;

	if (mgr && sysfs_streq(mgr->name, "tv")) {
		ovl->get_overlay_info(ovl, &info);
		if (mgr->device->panel.timings.x_res < info.out_width ||
			mgr->device->panel.timings.y_res < info.out_height) {
			printk(KERN_ERR"output window size exceeds panel dimensions");
			return -EINVAL;
		}
	}

	old_mgr = ovl->manager;
	/* detach old manager */
	if (old_mgr) {
		r = ovl->unset_manager(ovl);
		if (r) {
			DSSERR("detach failed\n");
			return r;
		}

		r = old_mgr->apply(old_mgr);
		if (r)
			return r;
	}

	if (mgr) {
		r = ovl->set_manager(ovl, mgr);
		if (r) {
			DSSERR("Failed to attach overlay\n");
			return r;
		}

		r = mgr->apply(mgr);
		if (r)
			return r;
	}

	return size;
}