Commit 51919572 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Tomi Valkeinen

drm: omapdrm: Move supported outputs feature to dss driver

The supported outputs feature is specific to the DSS, move it from the
omap_dss_features structure to the dss driver.

The omap_dss_features structure is now empty and can be removed.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
parent 9f0fbaea
...@@ -5,7 +5,7 @@ omapdss-base-y := base.o display.o dss-of.o output.o ...@@ -5,7 +5,7 @@ omapdss-base-y := base.o display.o dss-of.o output.o
obj-$(CONFIG_OMAP2_DSS) += omapdss.o obj-$(CONFIG_OMAP2_DSS) += omapdss.o
# Core DSS files # Core DSS files
omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o \ omapdss-y := core.o dss.o dispc.o dispc_coefs.o \
pll.o video-pll.o pll.o video-pll.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
......
...@@ -54,8 +54,6 @@ static int __init omap_dss_probe(struct platform_device *pdev) ...@@ -54,8 +54,6 @@ static int __init omap_dss_probe(struct platform_device *pdev)
{ {
core.pdev = pdev; core.pdev = pdev;
dss_features_init(omapdss_get_version());
return 0; return 0;
} }
......
...@@ -2736,7 +2736,7 @@ static int dispc_ovl_enable(enum omap_plane_id plane, bool enable) ...@@ -2736,7 +2736,7 @@ static int dispc_ovl_enable(enum omap_plane_id plane, bool enable)
static enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel) static enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel)
{ {
return dss_feat_get_supported_outputs(channel); return dss_get_supported_outputs(channel);
} }
static void dispc_lcd_enable_signal_polarity(bool act_high) static void dispc_lcd_enable_signal_polarity(bool act_high)
......
...@@ -86,6 +86,7 @@ struct dss_features { ...@@ -86,6 +86,7 @@ struct dss_features {
const char *parent_clk_name; const char *parent_clk_name;
const enum omap_display_type *ports; const enum omap_display_type *ports;
int num_ports; int num_ports;
const enum omap_dss_output_id *outputs;
const struct dss_ops *ops; const struct dss_ops *ops;
struct dss_reg_field dispc_clk_switch; struct dss_reg_field dispc_clk_switch;
bool has_lcd_clk_src; bool has_lcd_clk_src;
...@@ -150,8 +151,7 @@ static void dss_save_context(void) ...@@ -150,8 +151,7 @@ static void dss_save_context(void)
SR(CONTROL); SR(CONTROL);
if (dss_feat_get_supported_outputs(OMAP_DSS_CHANNEL_LCD) & if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
OMAP_DSS_OUTPUT_SDI) {
SR(SDI_CONTROL); SR(SDI_CONTROL);
SR(PLL_CONTROL); SR(PLL_CONTROL);
} }
...@@ -170,8 +170,7 @@ static void dss_restore_context(void) ...@@ -170,8 +170,7 @@ static void dss_restore_context(void)
RR(CONTROL); RR(CONTROL);
if (dss_feat_get_supported_outputs(OMAP_DSS_CHANNEL_LCD) & if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
OMAP_DSS_OUTPUT_SDI) {
RR(SDI_CONTROL); RR(SDI_CONTROL);
RR(PLL_CONTROL); RR(PLL_CONTROL);
} }
...@@ -401,8 +400,7 @@ static void dss_dump_regs(struct seq_file *s) ...@@ -401,8 +400,7 @@ static void dss_dump_regs(struct seq_file *s)
DUMPREG(DSS_SYSSTATUS); DUMPREG(DSS_SYSSTATUS);
DUMPREG(DSS_CONTROL); DUMPREG(DSS_CONTROL);
if (dss_feat_get_supported_outputs(OMAP_DSS_CHANNEL_LCD) & if (dss.feat->outputs[OMAP_DSS_CHANNEL_LCD] & OMAP_DSS_OUTPUT_SDI) {
OMAP_DSS_OUTPUT_SDI) {
DUMPREG(DSS_SDI_CONTROL); DUMPREG(DSS_SDI_CONTROL);
DUMPREG(DSS_PLL_CONTROL); DUMPREG(DSS_PLL_CONTROL);
DUMPREG(DSS_SDI_STATUS); DUMPREG(DSS_SDI_STATUS);
...@@ -687,6 +685,11 @@ unsigned long dss_get_max_fck_rate(void) ...@@ -687,6 +685,11 @@ unsigned long dss_get_max_fck_rate(void)
return dss.feat->fck_freq_max; return dss.feat->fck_freq_max;
} }
enum omap_dss_output_id dss_get_supported_outputs(enum omap_channel channel)
{
return dss.feat->outputs[channel];
}
static int dss_setup_default_clock(void) static int dss_setup_default_clock(void)
{ {
unsigned long max_dss_fck, prate; unsigned long max_dss_fck, prate;
...@@ -737,7 +740,7 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src) ...@@ -737,7 +740,7 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
{ {
enum omap_dss_output_id outputs; enum omap_dss_output_id outputs;
outputs = dss_feat_get_supported_outputs(OMAP_DSS_CHANNEL_DIGIT); outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT];
/* Complain about invalid selections */ /* Complain about invalid selections */
WARN_ON((src == DSS_VENC_TV_CLK) && !(outputs & OMAP_DSS_OUTPUT_VENC)); WARN_ON((src == DSS_VENC_TV_CLK) && !(outputs & OMAP_DSS_OUTPUT_VENC));
...@@ -753,7 +756,7 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) ...@@ -753,7 +756,7 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
{ {
enum omap_dss_output_id outputs; enum omap_dss_output_id outputs;
outputs = dss_feat_get_supported_outputs(OMAP_DSS_CHANNEL_DIGIT); outputs = dss.feat->outputs[OMAP_DSS_CHANNEL_DIGIT];
if ((outputs & OMAP_DSS_OUTPUT_HDMI) == 0) if ((outputs & OMAP_DSS_OUTPUT_HDMI) == 0)
return DSS_VENC_TV_CLK; return DSS_VENC_TV_CLK;
...@@ -1004,6 +1007,66 @@ static const enum omap_display_type dra7xx_ports[] = { ...@@ -1004,6 +1007,66 @@ static const enum omap_display_type dra7xx_ports[] = {
OMAP_DISPLAY_TYPE_DPI, OMAP_DISPLAY_TYPE_DPI,
}; };
static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC,
};
static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC,
};
static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI1,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC,
};
static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
};
static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
/* OMAP_DSS_CHANNEL_LCD2 */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI2,
};
static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_HDMI,
/* OMAP_DSS_CHANNEL_LCD2 */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI1,
/* OMAP_DSS_CHANNEL_LCD3 */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI2,
};
static const struct dss_features omap24xx_dss_feats = { static const struct dss_features omap24xx_dss_feats = {
.model = DSS_MODEL_OMAP2, .model = DSS_MODEL_OMAP2,
/* /*
...@@ -1016,6 +1079,7 @@ static const struct dss_features omap24xx_dss_feats = { ...@@ -1016,6 +1079,7 @@ static const struct dss_features omap24xx_dss_feats = {
.parent_clk_name = "core_ck", .parent_clk_name = "core_ck",
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports), .num_ports = ARRAY_SIZE(omap2plus_ports),
.outputs = omap2_dss_supported_outputs,
.ops = &dss_ops_omap2_omap3, .ops = &dss_ops_omap2_omap3,
.dispc_clk_switch = { 0, 0 }, .dispc_clk_switch = { 0, 0 },
.has_lcd_clk_src = false, .has_lcd_clk_src = false,
...@@ -1028,6 +1092,7 @@ static const struct dss_features omap34xx_dss_feats = { ...@@ -1028,6 +1092,7 @@ static const struct dss_features omap34xx_dss_feats = {
.dss_fck_multiplier = 2, .dss_fck_multiplier = 2,
.parent_clk_name = "dpll4_ck", .parent_clk_name = "dpll4_ck",
.ports = omap34xx_ports, .ports = omap34xx_ports,
.outputs = omap3430_dss_supported_outputs,
.num_ports = ARRAY_SIZE(omap34xx_ports), .num_ports = ARRAY_SIZE(omap34xx_ports),
.ops = &dss_ops_omap2_omap3, .ops = &dss_ops_omap2_omap3,
.dispc_clk_switch = { 0, 0 }, .dispc_clk_switch = { 0, 0 },
...@@ -1042,6 +1107,7 @@ static const struct dss_features omap3630_dss_feats = { ...@@ -1042,6 +1107,7 @@ static const struct dss_features omap3630_dss_feats = {
.parent_clk_name = "dpll4_ck", .parent_clk_name = "dpll4_ck",
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports), .num_ports = ARRAY_SIZE(omap2plus_ports),
.outputs = omap3630_dss_supported_outputs,
.ops = &dss_ops_omap2_omap3, .ops = &dss_ops_omap2_omap3,
.dispc_clk_switch = { 0, 0 }, .dispc_clk_switch = { 0, 0 },
.has_lcd_clk_src = false, .has_lcd_clk_src = false,
...@@ -1055,6 +1121,7 @@ static const struct dss_features omap44xx_dss_feats = { ...@@ -1055,6 +1121,7 @@ static const struct dss_features omap44xx_dss_feats = {
.parent_clk_name = "dpll_per_x2_ck", .parent_clk_name = "dpll_per_x2_ck",
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports), .num_ports = ARRAY_SIZE(omap2plus_ports),
.outputs = omap4_dss_supported_outputs,
.ops = &dss_ops_omap4, .ops = &dss_ops_omap4,
.dispc_clk_switch = { 9, 8 }, .dispc_clk_switch = { 9, 8 },
.has_lcd_clk_src = true, .has_lcd_clk_src = true,
...@@ -1068,6 +1135,7 @@ static const struct dss_features omap54xx_dss_feats = { ...@@ -1068,6 +1135,7 @@ static const struct dss_features omap54xx_dss_feats = {
.parent_clk_name = "dpll_per_x2_ck", .parent_clk_name = "dpll_per_x2_ck",
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports), .num_ports = ARRAY_SIZE(omap2plus_ports),
.outputs = omap5_dss_supported_outputs,
.ops = &dss_ops_omap5, .ops = &dss_ops_omap5,
.dispc_clk_switch = { 9, 7 }, .dispc_clk_switch = { 9, 7 },
.has_lcd_clk_src = true, .has_lcd_clk_src = true,
...@@ -1081,6 +1149,7 @@ static const struct dss_features am43xx_dss_feats = { ...@@ -1081,6 +1149,7 @@ static const struct dss_features am43xx_dss_feats = {
.parent_clk_name = NULL, .parent_clk_name = NULL,
.ports = omap2plus_ports, .ports = omap2plus_ports,
.num_ports = ARRAY_SIZE(omap2plus_ports), .num_ports = ARRAY_SIZE(omap2plus_ports),
.outputs = am43xx_dss_supported_outputs,
.ops = &dss_ops_omap2_omap3, .ops = &dss_ops_omap2_omap3,
.dispc_clk_switch = { 0, 0 }, .dispc_clk_switch = { 0, 0 },
.has_lcd_clk_src = true, .has_lcd_clk_src = true,
...@@ -1094,6 +1163,7 @@ static const struct dss_features dra7xx_dss_feats = { ...@@ -1094,6 +1163,7 @@ static const struct dss_features dra7xx_dss_feats = {
.parent_clk_name = "dpll_per_x2_ck", .parent_clk_name = "dpll_per_x2_ck",
.ports = dra7xx_ports, .ports = dra7xx_ports,
.num_ports = ARRAY_SIZE(dra7xx_ports), .num_ports = ARRAY_SIZE(dra7xx_ports),
.outputs = omap5_dss_supported_outputs,
.ops = &dss_ops_dra7, .ops = &dss_ops_dra7,
.dispc_clk_switch = { 9, 7 }, .dispc_clk_switch = { 9, 7 },
.has_lcd_clk_src = true, .has_lcd_clk_src = true,
......
...@@ -266,6 +266,7 @@ void dss_runtime_put(void); ...@@ -266,6 +266,7 @@ void dss_runtime_put(void);
unsigned long dss_get_dispc_clk_rate(void); unsigned long dss_get_dispc_clk_rate(void);
unsigned long dss_get_max_fck_rate(void); unsigned long dss_get_max_fck_rate(void);
enum omap_dss_output_id dss_get_supported_outputs(enum omap_channel channel);
int dss_dpi_select_source(int port, enum omap_channel channel); int dss_dpi_select_source(int port, enum omap_channel channel);
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
......
/*
* linux/drivers/video/omap2/dss/dss_features.c
*
* Copyright (C) 2010 Texas Instruments
* Author: Archit Taneja <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <drm/drm_fourcc.h>
#include "omapdss.h"
#include "dss.h"
#include "dss_features.h"
struct omap_dss_features {
const enum omap_dss_output_id *supported_outputs;
};
/* This struct is assigned to one of the below during initialization */
static const struct omap_dss_features *omap_current_dss_features;
static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC,
};
static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC,
};
static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI1,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC,
};
static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
};
static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
/* OMAP_DSS_CHANNEL_LCD2 */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI2,
};
static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
/* OMAP_DSS_CHANNEL_LCD */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
/* OMAP_DSS_CHANNEL_DIGIT */
OMAP_DSS_OUTPUT_HDMI,
/* OMAP_DSS_CHANNEL_LCD2 */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI1,
/* OMAP_DSS_CHANNEL_LCD3 */
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
OMAP_DSS_OUTPUT_DSI2,
};
/* OMAP2 DSS Features */
static const struct omap_dss_features omap2_dss_features = {
.supported_outputs = omap2_dss_supported_outputs,
};
/* OMAP3 DSS Features */
static const struct omap_dss_features omap3430_dss_features = {
.supported_outputs = omap3430_dss_supported_outputs,
};
/*
* AM35xx DSS Features. This is basically OMAP3 DSS Features without the
* vdds_dsi regulator.
*/
static const struct omap_dss_features am35xx_dss_features = {
.supported_outputs = omap3430_dss_supported_outputs,
};
static const struct omap_dss_features am43xx_dss_features = {
.supported_outputs = am43xx_dss_supported_outputs,
};
static const struct omap_dss_features omap3630_dss_features = {
.supported_outputs = omap3630_dss_supported_outputs,
};
/* OMAP4 DSS Features */
/* For OMAP4430 ES 1.0 revision */
static const struct omap_dss_features omap4430_es1_0_dss_features = {
.supported_outputs = omap4_dss_supported_outputs,
};
/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */
static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
.supported_outputs = omap4_dss_supported_outputs,
};
/* For all the other OMAP4 versions */
static const struct omap_dss_features omap4_dss_features = {
.supported_outputs = omap4_dss_supported_outputs,
};
/* OMAP5 DSS Features */
static const struct omap_dss_features omap5_dss_features = {
.supported_outputs = omap5_dss_supported_outputs,
};
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
{
return omap_current_dss_features->supported_outputs[channel];
}
void dss_features_init(enum omapdss_version version)
{
switch (version) {
case OMAPDSS_VER_OMAP24xx:
omap_current_dss_features = &omap2_dss_features;
break;
case OMAPDSS_VER_OMAP34xx_ES1:
case OMAPDSS_VER_OMAP34xx_ES3:
omap_current_dss_features = &omap3430_dss_features;
break;
case OMAPDSS_VER_OMAP3630:
omap_current_dss_features = &omap3630_dss_features;
break;
case OMAPDSS_VER_OMAP4430_ES1:
omap_current_dss_features = &omap4430_es1_0_dss_features;
break;
case OMAPDSS_VER_OMAP4430_ES2:
omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
break;
case OMAPDSS_VER_OMAP4:
omap_current_dss_features = &omap4_dss_features;
break;
case OMAPDSS_VER_OMAP5:
case OMAPDSS_VER_DRA7xx:
omap_current_dss_features = &omap5_dss_features;
break;
case OMAPDSS_VER_AM35xx:
omap_current_dss_features = &am35xx_dss_features;
break;
case OMAPDSS_VER_AM43xx:
omap_current_dss_features = &am43xx_dss_features;
break;
default:
DSSWARN("Unsupported OMAP version");
break;
}
}
...@@ -25,8 +25,4 @@ ...@@ -25,8 +25,4 @@
#define MAX_DSS_LCD_MANAGERS 3 #define MAX_DSS_LCD_MANAGERS 3
#define MAX_NUM_DSI 2 #define MAX_NUM_DSI 2
void dss_features_init(enum omapdss_version version);
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment