### Summary

An exception is thrown when an argspec expecting a dict with suboptions is given a string.
This only occurs when the argument in the argspec has suboptions.

### Issue Type

Bug Report

### Component Name

module_utils/common/parameters.py

### Ansible Version

```console
ansible [core 2.11.4]
```


### Configuration

```console
$ ansible-config dump --only-changed
```


### OS / Environment

RHEL 8

### Steps to Reproduce

`meta/argument_specs.yml`
```yaml
---
argument_specs:
  main:
    options:
      dict_option:
        type: dict
        options:
          some_option:
            type: str
```
Playbook:
```
---
- hosts: localhost
  gather_facts: false
  vars:
    dict_option: this is a string
  roles:
    - test
```

### Expected Results

An exception should not be thrown.

### Actual Results

```console
The full traceback is:
Traceback (most recent call last):
  File "/home/user/ansible4/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 158, in run
    res = self._execute()
  File "/home/user/ansible4/lib/python3.8/site-packages/ansible/executor/task_executor.py", line 582, in _execute
    result = self._handler.run(task_vars=variables)
  File "/home/user/ansible4/lib/python3.8/site-packages/ansible/plugins/action/validate_argument_spec.py", line 83, in run
    validation_result = validator.validate(provided_arguments)
  File "/home/user/ansible4/lib/python3.8/site-packages/ansible/module_utils/common/arg_spec.py", line 244, in validate
    _validate_sub_spec(self.argument_spec, result._validated_parameters,
  File "/home/user/ansible4/lib/python3.8/site-packages/ansible/module_utils/common/parameters.py", line 761, in _validate_sub_spec
    unsupported_parameters.update(_get_unsupported_parameters(sub_spec, sub_parameters, legal_inputs, options_context))
  File "/home/user/ansible4/lib/python3.8/site-packages/ansible/module_utils/common/parameters.py", line 177, in _get_unsupported_parameters
    for k in parameters.keys():
AttributeError: 'str' object has no attribute 'keys'
fatal: [localhost]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}
```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct
msg = "{0} found in {1}".format(msg, " -> ".join(options_context))
                        errors.append(ArgumentValueError(msg))
                elif parameters[param] not in choices:
                    
                    
                    lowered_choices = None
                    if parameters[param] == 'False':
                        lowered_choices = lenient_lowercase(choices)
                        overlap = BOOLEANS_FALSE.intersection(choices)
                        if len(overlap) == 1:
                            
                            (parameters[param],) = overlap
                    if parameters[param] == 'True':
                        if lowered_choices is None:
                            lowered_choices = lenient_lowercase(choices)
                        overlap = BOOLEANS_TRUE.intersection(choices)
                        if len(overlap) == 1:
                            (parameters[param],) = overlap
                    if parameters[param] not in choices:
                        choices_str = ", ".join([to_native(c) for c in choices])
                        msg = "value of %s must be one of: %s, got: %s" % (param, choices_str, parameters[param])
                        if options_context:
                            msg = "{0} found in {1}".format(msg, " -> ".join(options_context))
                        errors.append(ArgumentValueError(msg))
        else:
            msg = "internal error: choices for argument %s are not iterable: %s" % (param, choices)
            if options_context:
                msg = "{0} found in {1}".format(msg, " -> ".join(options_context))
            errors.append(ArgumentTypeError(msg))
def _validate_sub_spec(argument_spec, parameters, prefix='', options_context=None, errors=None, no_log_values=None, unsupported_parameters=None):