2 * NVIDIA Tegra CSI Device
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
6 * Author: Bryan Wu <pengw@nvidia.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/clk.h>
14 #include <linux/device.h>
15 #include <linux/gpio/consumer.h>
16 #include <linux/module.h>
18 #include <linux/of_graph.h>
19 #include <linux/platform_device.h>
20 #include <linux/of_platform.h>
22 #include <media/media-entity.h>
23 #include <media/v4l2-async.h>
24 #include <media/v4l2-ctrls.h>
25 #include <media/camera_common.h>
29 #include "camera/csi/csi.h"
30 #include "camera/vi/mc_common.h"
31 #include "mipical/mipi_cal.h"
32 #include "linux/nvhost.h"
34 static struct tegra_csi_device *mc_csi;
36 struct tegra_csi_device *tegra_get_mc_csi(void)
40 EXPORT_SYMBOL(tegra_get_mc_csi);
42 static int set_csi_properties(struct tegra_csi_device *csi,
43 struct platform_device *pdev)
45 struct camera_common_data *s_data = &csi->s_data[0];
48 * These values are only used for tpg mode
49 * With sensor, CSI power and clock info are provided
50 * by the sensor sub device
53 s_data->numlanes = 12;
54 csi->clk_freq = TEGRA_CLOCK_CSI_PORT_MAX;
59 static void update_blank_intervals(struct tegra_csi_channel *chan,
60 int portnum, int fmtindex)
62 struct tegra_csi_port *port = &chan->ports[portnum];
63 const struct tpg_frmfmt *tegra_csi_tpg_frmfmt =
64 chan->csi->tpg_frmfmt_table;
66 port->framerate = tegra_csi_tpg_frmfmt[fmtindex].framerate;
67 port->h_blank = tegra_csi_tpg_frmfmt[fmtindex].h_blank;
68 port->v_blank = tegra_csi_tpg_frmfmt[fmtindex].v_blank;
71 void set_csi_portinfo(struct tegra_csi_device *csi,
72 unsigned int port, unsigned int numlanes)
74 struct camera_common_data *s_data = &csi->s_data[port];
76 s_data->csi_port = port;
77 s_data->numlanes = numlanes;
78 s_data->def_clk_freq = TEGRA_CLOCK_CSI_PORT_MAX;
80 EXPORT_SYMBOL(set_csi_portinfo);
82 static int tegra_csi_power(struct tegra_csi_device *csi,
83 struct tegra_csi_channel *chan, int enable)
88 err = csi->fops->csi_power_on(csi);
90 atomic_inc(&csi->power_ref);
92 err = csi->fops->csi_power_off(csi);
94 atomic_dec(&csi->power_ref);
98 EXPORT_SYMBOL(tegra_csi_power);
100 int tegra_csi_s_power(struct v4l2_subdev *subdev, int enable)
103 struct tegra_csi_device *csi = to_csi(subdev);
104 struct tegra_csi_channel *chan = to_csi_chan(subdev);
106 err = tegra_csi_power(csi, chan, enable);
112 * -----------------------------------------------------------------------------
113 * CSI Subdevice Video Operations
114 * -----------------------------------------------------------------------------
117 int tegra_csi_start_streaming(struct tegra_csi_channel *chan,
118 enum tegra_csi_port_num port_num)
120 struct tegra_csi_device *csi = chan->csi;
122 return csi->fops->csi_start_streaming(chan, port_num);
124 EXPORT_SYMBOL(tegra_csi_start_streaming);
126 void tegra_csi_stop_streaming(struct tegra_csi_channel *chan,
127 enum tegra_csi_port_num port_num)
129 struct tegra_csi_device *csi = chan->csi;
131 csi->fops->csi_stop_streaming(chan, port_num);
133 EXPORT_SYMBOL(tegra_csi_stop_streaming);
135 static int update_video_source(struct tegra_csi_device *csi, int on, int is_tpg)
137 mutex_lock(&csi->source_update);
142 csi->sensor_active--;
143 WARN_ON(csi->tpg_active < 0 || csi->sensor_active < 0);
146 if (is_tpg && csi->tpg_active >= 0 && !csi->sensor_active) {
150 if (!is_tpg && csi->sensor_active >= 0 && !csi->tpg_active) {
151 csi->sensor_active++;
154 mutex_unlock(&csi->source_update);
155 dev_err(csi->dev, "Request rejected for new %s stream\n",
156 is_tpg ? "tpg" : "sensor");
157 dev_err(csi->dev, "Active tpg streams %d, active sensor streams %d\n",
158 csi->tpg_active, csi->sensor_active);
161 mutex_unlock(&csi->source_update);
164 static int tegra_csi_s_stream(struct v4l2_subdev *subdev, int enable)
166 struct tegra_csi_device *csi;
167 struct tegra_csi_channel *chan = to_csi_chan(subdev);
168 struct tegra_channel *tegra_chan = v4l2_get_subdev_hostdata(subdev);
171 if (atomic_read(&chan->is_streaming) == enable)
173 csi = to_csi(subdev);
176 ret = update_video_source(csi, enable, chan->pg_mode);
180 if (tegra_chan->bypass) {
181 atomic_set(&chan->is_streaming, enable);
185 for (i = 0; i < tegra_chan->valid_ports; i++) {
187 ret = tegra_csi_start_streaming(chan, i);
191 tegra_csi_stop_streaming(chan, i);
193 atomic_set(&chan->is_streaming, enable);
196 update_video_source(csi, 0, chan->pg_mode);
197 for (i = 0; i < tegra_chan->valid_ports; i++)
198 tegra_csi_stop_streaming(chan, i);
203 /* Used to calculate the settling time based on the mipi and cil clocks */
204 unsigned int tegra_csi_ths_settling_time(
205 struct tegra_csi_device *csi,
206 const unsigned int csicil_clk_mhz,
207 const unsigned int mipi_clk_mhz)
209 unsigned int cil_settletime;
211 cil_settletime = (115 * csicil_clk_mhz + 8000 * csicil_clk_mhz
212 / (2 * mipi_clk_mhz) - 5500) / 1000;
213 return cil_settletime;
215 EXPORT_SYMBOL(tegra_csi_ths_settling_time);
217 unsigned int tegra_csi_clk_settling_time(
218 struct tegra_csi_device *csi,
219 const unsigned int csicil_clk_mhz)
221 unsigned int clk_settletime;
223 clk_settletime = ((95 + 300) * csicil_clk_mhz - 13000) / 2000;
224 return clk_settletime;
226 EXPORT_SYMBOL(tegra_csi_clk_settling_time);
229 * Only use this subdevice media bus ops for test pattern generator,
230 * because CSI device is an separated subdevice which has 6 source
231 * pads to generate test pattern.
233 static struct v4l2_mbus_framefmt tegra_csi_tpg_fmts[] = {
237 MEDIA_BUS_FMT_SRGGB10_1X10,
244 MEDIA_BUS_FMT_RGB888_1X32_PADHI,
251 static struct v4l2_frmsize_discrete tegra_csi_tpg_sizes[] = {
257 static int tegra_csi_enum_framesizes(struct v4l2_subdev *sd,
258 struct v4l2_subdev_pad_config *cfg,
259 struct v4l2_subdev_frame_size_enum *fse)
262 struct tegra_csi_channel *chan = to_csi_chan(sd);
263 struct tegra_channel *vi_chan = v4l2_get_subdev_hostdata(sd);
268 if (fse->index >= ARRAY_SIZE(tegra_csi_tpg_sizes))
271 for (i = 0; i < ARRAY_SIZE(tegra_csi_tpg_fmts); i++) {
272 const struct tegra_video_format *format =
273 tegra_core_get_format_by_code(vi_chan,
274 tegra_csi_tpg_fmts[i].code, 0);
275 if (format && format->fourcc == fse->code)
278 if (i == ARRAY_SIZE(tegra_csi_tpg_fmts))
281 fse->min_width = fse->max_width =
282 tegra_csi_tpg_sizes[fse->index].width;
283 fse->min_height = fse->max_height =
284 tegra_csi_tpg_sizes[fse->index].height;
288 static int tegra_csi_get_fmtindex(struct tegra_csi_channel *chan,
289 int width, int height, int pixel_format)
292 const struct tpg_frmfmt *tegra_csi_tpg_frmfmt =
293 chan->csi->tpg_frmfmt_table;
295 for (i = 0; i < chan->csi->tpg_frmfmt_table_size; i++) {
296 if (tegra_csi_tpg_frmfmt[i].frmsize.width == width &&
297 tegra_csi_tpg_frmfmt[i].frmsize.height == height &&
298 tegra_csi_tpg_frmfmt[i].pixel_format == pixel_format)
302 if (i == chan->csi->tpg_frmfmt_table_size)
308 static int tegra_csi_enum_frameintervals(struct v4l2_subdev *sd,
309 struct v4l2_subdev_pad_config *cfg,
310 struct v4l2_subdev_frame_interval_enum *fie)
313 struct tegra_csi_channel *chan = to_csi_chan(sd);
314 const struct tegra_video_format *format;
315 const struct tpg_frmfmt *tegra_csi_tpg_frmfmt =
316 chan->csi->tpg_frmfmt_table;
317 struct tegra_channel *vi_chan = v4l2_get_subdev_hostdata(sd);
322 /* One resolution just one framerate */
325 format = tegra_core_get_format_by_fourcc(vi_chan, fie->code);
328 index = tegra_csi_get_fmtindex(chan, fie->width, fie->height,
333 fie->interval.numerator = 1;
334 fie->interval.denominator = tegra_csi_tpg_frmfmt[index].framerate;
339 static int tegra_csi_try_mbus_fmt(struct v4l2_subdev *sd,
340 struct v4l2_mbus_framefmt *mf)
343 struct tegra_csi_channel *chan = to_csi_chan(sd);
344 static struct v4l2_frmsize_discrete *sizes;
349 for (i = 0; i < ARRAY_SIZE(tegra_csi_tpg_fmts); i++) {
350 struct v4l2_mbus_framefmt *fmt = &tegra_csi_tpg_fmts[i];
352 if (mf->code == fmt->code && mf->field == fmt->field &&
353 mf->colorspace == fmt->colorspace) {
354 for (j = 0; j < ARRAY_SIZE(tegra_csi_tpg_sizes); j++) {
355 sizes = &tegra_csi_tpg_sizes[j];
356 if (mf->width == sizes->width &&
357 mf->height == sizes->height)
363 memcpy(mf, tegra_csi_tpg_fmts, sizeof(struct v4l2_mbus_framefmt));
368 static int tegra_csi_g_mbus_fmt(struct v4l2_subdev *sd,
369 struct v4l2_mbus_framefmt *fmt)
371 struct tegra_csi_channel *chan = to_csi_chan(sd);
372 struct v4l2_mbus_framefmt *format = &chan->ports[0].format;
374 if (!chan->pg_mode) {
375 dev_err(chan->csi->dev, "CSI is not in TPG mode\n");
379 mutex_lock(&chan->format_lock);
380 memcpy(fmt, format, sizeof(struct v4l2_mbus_framefmt));
381 mutex_unlock(&chan->format_lock);
386 static int csi_is_power_on(struct tegra_csi_device *csi)
388 return atomic_read(&csi->power_ref);
390 static int tegra_csi_g_input_status(struct v4l2_subdev *sd, u32 *status)
392 struct tegra_csi_device *csi = to_csi(sd);
394 /* Set status to 0 if power is on
395 * Set status to 1 if power is off
397 *status = !csi_is_power_on(csi);
402 /* -----------------------------------------------------------------------------
403 * V4L2 Subdevice Pad Operations
406 static int tegra_csi_get_format(struct v4l2_subdev *subdev,
407 struct v4l2_subdev_pad_config *cfg,
408 struct v4l2_subdev_format *fmt)
410 struct tegra_csi_channel *chan = to_csi_chan(subdev);
411 struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format;
416 ret = tegra_csi_g_mbus_fmt(subdev, mbus_fmt);
423 static int tegra_csi_set_format(struct v4l2_subdev *subdev,
424 struct v4l2_subdev_pad_config *cfg,
425 struct v4l2_subdev_format *fmt)
428 struct tegra_csi_channel *chan = to_csi_chan(subdev);
429 struct v4l2_mbus_framefmt *format = &fmt->format;
430 const struct tegra_video_format *vf;
431 struct tegra_channel *vi_chan = v4l2_get_subdev_hostdata(subdev);
437 ret = tegra_csi_try_mbus_fmt(subdev, format);
441 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
444 vf = tegra_core_get_format_by_code(vi_chan, format->code, 0);
446 dev_err(chan->csi->dev, "Fail to find tegra video fmt");
447 mutex_unlock(&chan->format_lock);
450 index = tegra_csi_get_fmtindex(chan, format->width,
451 format->height, vf->fourcc);
453 dev_err(chan->csi->dev, "Fail to find matching fmt");
457 mutex_lock(&chan->format_lock);
458 for (i = 0; i < vi_chan->valid_ports; i++) {
459 memcpy(&chan->ports[i].format,
460 &fmt->format, sizeof(struct v4l2_mbus_framefmt));
461 chan->ports[i].core_format = vf;
462 update_blank_intervals(chan, i, index);
464 mutex_unlock(&chan->format_lock);
469 static int tegra_csi_g_frame_interval(struct v4l2_subdev *sd,
470 struct v4l2_subdev_frame_interval *vfi)
472 struct tegra_csi_channel *chan = to_csi_chan(sd);
473 struct tegra_csi_port *port = &chan->ports[0];
475 if (!port->framerate)
478 vfi->interval.numerator = 1;
479 vfi->interval.denominator = port->framerate;
484 /* -----------------------------------------------------------------------------
485 * V4L2 Subdevice Operations
487 static struct v4l2_subdev_video_ops tegra_csi_video_ops = {
488 .s_stream = tegra_csi_s_stream,
489 .g_input_status = tegra_csi_g_input_status,
490 .g_frame_interval = tegra_csi_g_frame_interval,
493 static struct v4l2_subdev_pad_ops tegra_csi_pad_ops = {
494 .get_fmt = tegra_csi_get_format,
495 .set_fmt = tegra_csi_set_format,
496 .enum_frame_size = tegra_csi_enum_framesizes,
497 .enum_frame_interval = tegra_csi_enum_frameintervals,
500 static struct v4l2_subdev_core_ops tegra_csi_core_ops = {
501 .s_power = tegra_csi_s_power,
504 static struct v4l2_subdev_ops tegra_csi_ops = {
505 .core = &tegra_csi_core_ops,
506 .video = &tegra_csi_video_ops,
507 .pad = &tegra_csi_pad_ops,
510 /* -----------------------------------------------------------------------------
514 static const struct media_entity_operations tegra_csi_media_ops = {
515 .link_validate = v4l2_subdev_link_validate,
518 /* -----------------------------------------------------------------------------
519 * Platform Device Driver
522 static int tegra_csi_get_port_info(struct tegra_csi_channel *chan,
523 struct device_node *node, unsigned int index)
525 struct device_node *ep = NULL;
526 struct device_node *ports;
527 struct device_node *port;
528 struct device_node *chan_dt;
533 memset(&chan->port[0], INVALID_CSI_PORT, TEGRA_CSI_BLOCKS);
534 for_each_child_of_node(node, chan_dt) {
535 if (!chan_dt->name || of_node_cmp(chan_dt->name, "channel"))
537 ret = of_property_read_u32(chan_dt, "reg", &value);
540 chan->of_node = chan_dt;
545 chan->subdev.of_node = chan_dt;
546 ports = of_get_child_by_name(chan_dt, "ports");
550 for_each_child_of_node(ports, port) {
551 if (!port->name || of_node_cmp(port->name, "port"))
553 ret = of_property_read_u32(port, "reg", &value);
558 for_each_child_of_node(port, ep) {
559 if (!ep->name || of_node_cmp(ep->name, "endpoint"))
561 ret = of_property_read_u32(ep, "csi-port", &value);
563 dev_err(chan->csi->dev, "No csi port info\n");
564 chan->port[0] = value;
566 ret = of_property_read_u32(ep, "bus-width", &value);
568 dev_err(chan->csi->dev, "No bus width info\n");
569 chan->numlanes = value;
571 dev_err(chan->csi->dev, "Invalid num lanes\n");
575 * for numlanes greater than 4 multiple CSI bricks
576 * are needed to capture the image, the logic below
577 * checks for numlanes > 4 and add a new CSI brick
578 * as a valid port. Loops around the three CSI
579 * bricks to add as many ports necessary.
582 for (i = 1; value > 0; i++, value -= 4) {
583 int next_port = chan->port[i-1] + 2;
585 next_port = (next_port % (PORT_F + 1));
586 chan->port[i] = next_port;
591 for (i = 0; csi_port_is_valid(chan->port[i]); i++)
597 int tegra_csi_init(struct tegra_csi_device *csi,
598 struct platform_device *pdev)
601 struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
603 csi->dev = &pdev->dev;
604 err = set_csi_properties(csi, pdev);
608 csi->iomem_base = pdata->aperture[0];
609 csi->fops->hw_init(csi);
613 static int tegra_csi_channel_init_one(struct tegra_csi_channel *chan)
615 struct v4l2_subdev *sd;
617 struct tegra_csi_device *csi = chan->csi;
619 const struct tegra_video_format *vf;
621 mutex_init(&chan->format_lock);
623 vf = tegra_core_get_default_format();
625 dev_err(csi->dev, "Fail to find tegra video fmt");
629 atomic_set(&chan->is_streaming, 0);
631 /* Initialize V4L2 subdevice and media entity */
632 v4l2_subdev_init(sd, &tegra_csi_ops);
633 sd->dev = chan->csi->dev;
634 v4l2_set_subdevdata(sd, csi);
635 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
636 sd->entity.ops = &tegra_csi_media_ops;
637 chan->ports = devm_kzalloc(csi->dev,
638 chan->numports * sizeof(struct tegra_csi_port),
643 /* Initialize the default format */
644 for (i = 0; i < chan->numports; i++) {
645 chan->ports[i].format.code = vf->vf_code;
646 chan->ports[i].format.field = V4L2_FIELD_NONE;
647 chan->ports[i].format.colorspace = V4L2_COLORSPACE_SRGB;
648 chan->ports[i].format.width = TEGRA_DEF_WIDTH;
649 chan->ports[i].format.height = TEGRA_DEF_HEIGHT;
650 chan->ports[i].core_format = vf;
653 /* If CSI has 2 existing channels, chan->id will start
654 * from 2 for the first TPG channel, which uses PORT_A(0).
655 * To get the correct PORT number, subtract existing number of
656 * channels from chan->id.
658 chan->port[0] = chan->id - csi->num_channels;
659 WARN_ON(chan->port[0] > TPG_CHANNELS);
660 chan->ports[0].num = chan->id - csi->num_channels;
661 chan->ports->lanes = 2;
662 chan->pads = devm_kzalloc(csi->dev, sizeof(*chan->pads),
666 chan->pads[0].flags = MEDIA_PAD_FL_SOURCE;
668 chan->pads = devm_kzalloc(csi->dev, 2 * sizeof(*chan->pads),
672 chan->pads[0].flags = MEDIA_PAD_FL_SINK;
673 chan->pads[1].flags = MEDIA_PAD_FL_SOURCE;
675 snprintf(sd->name, sizeof(sd->name), "%s-%d",
676 chan->pg_mode ? "tpg" :
677 (strlen(csi->devname) == 0 ?
678 dev_name(csi->dev) : csi->devname),
680 /* Initialize media entity */
681 ret = media_entity_init(&sd->entity,
682 chan->pg_mode ? 1 : 2,
687 for (i = 0; i < chan->numports; i++) {
688 numlanes = chan->numlanes - (i * MAX_CSI_BLOCK_LANES);
689 WARN_ON(numlanes < 0);
690 numlanes = numlanes > MAX_CSI_BLOCK_LANES ?
691 MAX_CSI_BLOCK_LANES : numlanes;
692 chan->ports[i].lanes = numlanes;
693 chan->ports[i].num = chan->port[i];
696 if (!chan->pg_mode) {
697 ret = v4l2_async_register_subdev(sd);
699 dev_err(csi->dev, "failed to register subdev\n");
700 media_entity_cleanup(&sd->entity);
706 static int tegra_csi_channels_init(struct tegra_csi_device *csi)
709 struct tegra_csi_channel *it;
711 list_for_each_entry(it, &csi->csi_chans, list) {
712 ret = tegra_csi_channel_init_one(it);
720 static int csi_parse_dt(struct tegra_csi_device *csi,
721 struct platform_device *pdev)
724 int num_channels = 0;
725 struct device_node *node = pdev->dev.of_node;
726 struct tegra_csi_channel *item;
728 if (strncmp(node->name, "nvcsi", 5)) {
729 node = of_find_node_by_name(node, "nvcsi");
730 strncpy(csi->devname, "nvcsi", 6);
734 err = of_property_read_u32(node, "num-channels", &num_channels);
736 dev_dbg(csi->dev, " Failed to find num of channels, set to 0\n");
740 csi->num_channels = num_channels;
741 for (i = 0; i < num_channels; i++) {
742 item = devm_kzalloc(csi->dev, sizeof(*item), GFP_KERNEL);
745 list_add_tail(&item->list, &csi->csi_chans);
748 err = tegra_csi_get_port_info(item, node, item->id);
756 int tpg_csi_media_controller_init(struct tegra_csi_device *csi, int pg_mode)
759 struct tegra_csi_channel *item;
763 for (i = 0; i < TPG_CHANNELS; i++) {
764 item = devm_kzalloc(csi->dev, sizeof(*item), GFP_KERNEL);
767 goto channel_init_error;
770 csi->tpg_start = item;
771 list_add_tail(&item->list, &csi->csi_chans);
775 item->pg_mode = pg_mode;
776 item->id = csi->num_channels + i;
777 err = tegra_csi_channel_init_one(item);
779 goto channel_init_error;
781 csi->fops->hw_init(csi);
782 csi->num_channels += TPG_CHANNELS;
788 tpg_csi_media_controller_cleanup(csi);
789 dev_err(csi->dev, "%s: Error\n", __func__);
792 EXPORT_SYMBOL(tpg_csi_media_controller_init);
794 void tpg_csi_media_controller_cleanup(struct tegra_csi_device *csi)
796 struct tegra_csi_channel *item;
797 struct tegra_csi_channel *itemn;
798 struct v4l2_subdev *sd;
800 list_for_each_entry_safe(item, itemn, &csi->csi_chans, list) {
804 /* decrement media device entity count */
805 if (sd->entity.parent)
806 sd->entity.parent->entity_id--;
807 v4l2_device_unregister_subdev(sd);
808 media_entity_cleanup(&sd->entity);
809 list_del(&item->list);
810 devm_kfree(csi->dev, item);
812 csi->num_channels -= TPG_CHANNELS;
813 csi->tpg_start = NULL;
815 EXPORT_SYMBOL(tpg_csi_media_controller_cleanup);
817 int tegra_csi_mipi_calibrate(struct tegra_csi_device *csi,
820 struct tegra_csi_channel *chan;
823 tegra_mipi_bias_pad_disable();
827 tegra_mipi_bias_pad_enable();
828 list_for_each_entry(chan, &csi->csi_chans, list) {
834 ret = csi->fops->mipical(chan);
837 "calibration failed with %d error\n", ret);
843 int tegra_csi_media_controller_init(struct tegra_csi_device *csi,
844 struct platform_device *pdev)
852 csi->dev = &pdev->dev;
855 csi->sensor_active = 0;
856 atomic_set(&csi->power_ref, 0);
857 mutex_init(&csi->source_update);
858 INIT_LIST_HEAD(&csi->csi_chans);
859 ret = csi_parse_dt(csi, pdev);
864 * if there is no csi channels listed in DT,
865 * no need to init the channel and graph
867 if (csi->num_channels == 0)
870 ret = tegra_csi_channels_init(csi);
871 ret = tegra_csi_init(csi, pdev);
873 dev_err(&pdev->dev, "Failed to init csi property,clks\n");
877 EXPORT_SYMBOL(tegra_csi_media_controller_init);
879 int tegra_csi_media_controller_remove(struct tegra_csi_device *csi)
881 struct tegra_csi_channel *chan;
882 struct v4l2_subdev *sd;
884 list_for_each_entry(chan, &csi->csi_chans, list) {
886 v4l2_async_unregister_subdev(sd);
887 media_entity_cleanup(&sd->entity);
891 EXPORT_SYMBOL(tegra_csi_media_controller_remove);